1+ import javax .swing .*;
2+ import java .awt .*;
3+ import java .util .*;
4+ import java .util .List ;
5+
6+ public class WaterDistributionSystem extends JFrame {
7+
8+ private static final int V = 8 ;
9+ private static final int SOURCE = 0 ;
10+ private static final int SINK = 7 ;
11+ private int [][] capacity ;
12+ private int [][] flow ;
13+ private int totalFlow = 0 ;
14+
15+ private final String [] nodeNames = {"S" , "C1" , "C2" , "C3" , "C4" , "C5" , "C6" , "T" };
16+ private final Point [] nodePos = {
17+ new Point (50 , 200 ), new Point (200 , 100 ), new Point (200 , 300 ),
18+ new Point (350 , 50 ), new Point (350 , 200 ), new Point (350 , 350 ),
19+ new Point (500 , 100 ), new Point (650 , 200 )
20+ };
21+
22+ private List <Integer > currentPath = null ;
23+ private GraphPanel graphPanel ;
24+ private JLabel infoLabel ;
25+ private JButton nextStepBtn ;
26+
27+ public WaterDistributionSystem () {
28+ setTitle ("Water Distribution Max Flow - Ford Fulkerson (Edmonds-Karp)" );
29+ setSize (850 , 550 );
30+ setDefaultCloseOperation (JFrame .EXIT_ON_CLOSE );
31+ setLayout (new BorderLayout ());
32+
33+ initGraph ();
34+ graphPanel = new GraphPanel ();
35+ graphPanel .setBackground (Color .WHITE );
36+ add (graphPanel , BorderLayout .CENTER );
37+
38+ JPanel bottomPanel = new JPanel ();
39+ nextStepBtn = new JButton ("Find Next Augmenting Path" );
40+ infoLabel = new JLabel ("Total Flow: 0 MLD | Ready" );
41+ infoLabel .setFont (new Font ("Monospaced" , Font .BOLD , 14 ));
42+
43+ nextStepBtn .addActionListener (e -> executeNextStep ());
44+
45+ bottomPanel .add (nextStepBtn );
46+ bottomPanel .add (Box .createHorizontalStrut (20 ));
47+ bottomPanel .add (infoLabel );
48+ add (bottomPanel , BorderLayout .SOUTH );
49+
50+ setLocationRelativeTo (null );
51+ }
52+
53+ private void initGraph () {
54+ capacity = new int [V ][V ];
55+ flow = new int [V ][V ];
56+ capacity [0 ][1 ] = 20 ; capacity [0 ][2 ] = 15 ;
57+ capacity [1 ][3 ] = 10 ; capacity [1 ][4 ] = 10 ;
58+ capacity [2 ][4 ] = 5 ; capacity [2 ][5 ] = 10 ;
59+ capacity [3 ][6 ] = 10 ; capacity [4 ][6 ] = 10 ;
60+ capacity [5 ][7 ] = 10 ; capacity [6 ][7 ] = 20 ;
61+ }
62+
63+ private void executeNextStep () {
64+ int [] parent = new int [V ];
65+ Arrays .fill (parent , -1 );
66+ Queue <Integer > queue = new LinkedList <>();
67+ queue .add (SOURCE );
68+ parent [SOURCE ] = SOURCE ;
69+
70+ boolean foundPath = false ;
71+ while (!queue .isEmpty ()) {
72+ int u = queue .poll ();
73+ for (int v = 0 ; v < V ; v ++) {
74+ // Check residual capacity
75+ if (parent [v ] == -1 && capacity [u ][v ] - flow [u ][v ] > 0 ) {
76+ parent [v ] = u ;
77+ queue .add (v );
78+ if (v == SINK ) {
79+ foundPath = true ;
80+ break ;
81+ }
82+ }
83+ }
84+ if (foundPath ) break ;
85+ }
86+
87+ if (!foundPath ) {
88+ infoLabel .setText ("Total Flow: " + totalFlow + " MLD | MAXIMUM FLOW REACHED!" );
89+ infoLabel .setForeground (new Color (0 , 128 , 0 ));
90+ currentPath = null ;
91+ nextStepBtn .setEnabled (false );
92+ graphPanel .repaint ();
93+ return ;
94+ }
95+
96+ // Calculate bottleneck capacity
97+ int pathFlow = Integer .MAX_VALUE ;
98+ for (int v = SINK ; v != SOURCE ; v = parent [v ]) {
99+ int u = parent [v ];
100+ pathFlow = Math .min (pathFlow , capacity [u ][v ] - flow [u ][v ]);
101+ }
102+
103+ // Update flow and track current path for visualization
104+ currentPath = new ArrayList <>();
105+ currentPath .add (SINK );
106+ for (int v = SINK ; v != SOURCE ; v = parent [v ]) {
107+ int u = parent [v ];
108+ flow [u ][v ] += pathFlow ;
109+ flow [v ][u ] -= pathFlow ;
110+ currentPath .add (u );
111+ }
112+ Collections .reverse (currentPath );
113+ totalFlow += pathFlow ;
114+
115+ StringBuilder pathStr = new StringBuilder ("Path: " );
116+ for (int i = 0 ; i < currentPath .size (); i ++) {
117+ pathStr .append (nodeNames [currentPath .get (i )]);
118+ if (i < currentPath .size () - 1 ) pathStr .append ("->" );
119+ }
120+
121+ infoLabel .setText (String .format ("Total Flow: %d MLD | %s (+%d)" , totalFlow , pathStr .toString (), pathFlow ));
122+ graphPanel .repaint ();
123+ }
124+
125+ private class GraphPanel extends JPanel {
126+ @ Override
127+ protected void paintComponent (Graphics g ) {
128+ super .paintComponent (g );
129+ Graphics2D g2d = (Graphics2D ) g ;
130+ g2d .setRenderingHint (RenderingHints .KEY_ANTIALIASING , RenderingHints .VALUE_ANTIALIAS_ON );
131+
132+ // Draw all edges
133+ for (int u = 0 ; u < V ; u ++) {
134+ for (int v = 0 ; v < V ; v ++) {
135+ if (capacity [u ][v ] > 0 ) drawEdge (g2d , u , v );
136+ }
137+ }
138+
139+ // Draw all nodes
140+ for (int i = 0 ; i < V ; i ++) {
141+ int x = nodePos [i ].x ;
142+ int y = nodePos [i ].y ;
143+ g2d .setColor (new Color (173 , 216 , 230 ));
144+ g2d .fillOval (x - 20 , y - 20 , 40 , 40 );
145+ g2d .setColor (Color .BLACK );
146+ g2d .drawOval (x - 20 , y - 20 , 40 , 40 );
147+ g2d .setFont (new Font ("Arial" , Font .BOLD , 14 ));
148+ FontMetrics fm = g2d .getFontMetrics ();
149+ g2d .drawString (nodeNames [i ], x - fm .stringWidth (nodeNames [i ]) / 2 , y + fm .getAscent () / 2 - 2 );
150+ }
151+ }
152+
153+ private void drawEdge (Graphics2D g2d , int u , int v ) {
154+ boolean isHighlighted = false ;
155+ if (currentPath != null ) {
156+ for (int i = 0 ; i < currentPath .size () - 1 ; i ++) {
157+ if (currentPath .get (i ) == u && currentPath .get (i +1 ) == v ) {
158+ isHighlighted = true ;
159+ break ;
160+ }
161+ }
162+ }
163+
164+ g2d .setColor (isHighlighted ? Color .RED : Color .LIGHT_GRAY );
165+ g2d .setStroke (new BasicStroke (isHighlighted ? 3 : 1 ));
166+ g2d .drawLine (nodePos [u ].x , nodePos [u ].y , nodePos [v ].x , nodePos [v ].y );
167+
168+ // Label for Flow/Capacity
169+ int midX = (nodePos [u ].x + nodePos [v ].x ) / 2 ;
170+ int midY = (nodePos [u ].y + nodePos [v ].y ) / 2 ;
171+
172+ String label = flow [u ][v ] + "/" + capacity [u ][v ];
173+ g2d .setFont (new Font ("Arial" , Font .PLAIN , 12 ));
174+ FontMetrics fm = g2d .getFontMetrics ();
175+
176+ // Draw background for label clarity
177+ g2d .setColor (new Color (255 , 255 , 255 , 220 ));
178+ g2d .fillRect (midX - fm .stringWidth (label )/2 - 2 , midY - fm .getAscent (), fm .stringWidth (label ) + 4 , fm .getHeight ());
179+
180+ g2d .setColor (isHighlighted ? Color .RED : new Color (0 , 102 , 204 ));
181+ g2d .drawString (label , midX - fm .stringWidth (label )/2 , midY );
182+ }
183+ }
184+
185+ public static void main (String [] args ) {
186+ // Corrected the lambda arrow here
187+ SwingUtilities .invokeLater (() -> new WaterDistributionSystem ().setVisible (true ));
188+ }
189+ }
0 commit comments