1
+ import java .util .ArrayDeque ;
2
+ import java .util .Queue ;
3
+
4
+ /**
5
+ * This implementation of Edmonds-Karp algorithms returns the maximum flow in a
6
+ * Flow Network. It makes use of the Ford-Fulkerson method.
7
+ *
8
+ * @author Lukas Keul
9
+ * @author Florian Mercks
10
+ */
11
+ public class EdmondsKarpMaxFlow {
12
+
13
+ private long [][] edgeCapacity ;
14
+ private int [] parentNode ;
15
+ private boolean [] visitedNode ;
16
+ private long [][] maxFlowBetweenNodes ;
17
+
18
+ @ SuppressWarnings ("unused" )
19
+ private int numOfN , numOfE ;
20
+
21
+ public EdmondsKarpMaxFlow (int numberOfNodes , int numberOfEdges ) {
22
+ this .numOfN = numberOfNodes ;
23
+ this .numOfE = numberOfEdges ;
24
+ this .parentNode = new int [numOfN ];
25
+ this .visitedNode = new boolean [numOfN ];
26
+ this .edgeCapacity = new long [numOfN ][numOfN ];
27
+ this .maxFlowBetweenNodes = new long [numOfN ][numOfN ];
28
+ }
29
+
30
+ /**
31
+ * Returns the maximum Flow in a Flow Network
32
+ *
33
+ * @param flowSource
34
+ * represents the starting point of a maximum flow measurement in
35
+ * a flow network
36
+ * @param FlowTarget
37
+ * represents the end point of a maximum flow measurement in a
38
+ * flow network
39
+ * @return maximum flow in the considered flow network
40
+ */
41
+ public long getMaxFlow (int flowSource , int flowTarget ) {
42
+ while (true ) {
43
+ final Queue <Integer > flowSourceQueue = new ArrayDeque <Integer >();
44
+ flowSourceQueue .add (flowSource );
45
+
46
+ // iterate through unvisited flowsources
47
+ for (int i = 0 ; i < this .numOfN ; ++i )
48
+ visitedNode [i ] = false ;
49
+ visitedNode [flowSource ] = true ;
50
+
51
+ boolean isFlowSourceChecked = false ;
52
+ int currentFlowSource ;
53
+
54
+ // iterate throught the flowSourceQueue
55
+ while (!flowSourceQueue .isEmpty ()) {
56
+ // give out the last Element of the Queue
57
+ currentFlowSource = flowSourceQueue .peek ();
58
+
59
+ // if the currentFlowSource is the flowTarget, we are done
60
+ // iterating
61
+ if (currentFlowSource == flowTarget ) {
62
+ isFlowSourceChecked = true ;
63
+ break ;
64
+ }
65
+
66
+ // remove last element from flowSourceQueue
67
+ flowSourceQueue .remove ();
68
+
69
+ // iterate through the number of nodes to check capacity size
70
+ for (int i = 0 ; i < numOfN ; ++i ) {
71
+ // if capacity is greater than the expected flow
72
+ // then add the node to the flowSourceQueue
73
+ if (!visitedNode [i ]
74
+ && edgeCapacity [currentFlowSource ][i ] > maxFlowBetweenNodes [currentFlowSource ][i ]) {
75
+
76
+ visitedNode [i ] = true ;
77
+ flowSourceQueue .add (i );
78
+ parentNode [i ] = currentFlowSource ;
79
+ }
80
+ }
81
+ }
82
+ if (isFlowSourceChecked == false )
83
+ break ;
84
+
85
+ // subtract the maximum flow between the nodes from the edge
86
+ // capacity
87
+ long holdPartialResults = edgeCapacity [parentNode [flowTarget ]][flowTarget ]
88
+ - maxFlowBetweenNodes [parentNode [flowTarget ]][flowTarget ];
89
+
90
+ // do a breadth first search from target to source to find minimum
91
+ // needed capacity
92
+ for (int i = flowTarget ; i != flowSource ; i = parentNode [i ])
93
+ holdPartialResults = Math .min (holdPartialResults ,
94
+ (edgeCapacity [parentNode [i ]][i ] - maxFlowBetweenNodes [parentNode [i ]][i ]));
95
+
96
+ // add all minimum needed capacities to the maximum flow between the
97
+ // source and the target node
98
+ for (int i = flowTarget ; i != flowSource ; i = parentNode [i ]) {
99
+ maxFlowBetweenNodes [parentNode [i ]][i ] += holdPartialResults ;
100
+ maxFlowBetweenNodes [i ][parentNode [i ]] -= holdPartialResults ;
101
+ }
102
+ }
103
+
104
+ long result = 0 ;
105
+
106
+ // return the resulting maximum flow between the flowSource and the
107
+ // flowTarget
108
+ for (int i = 0 ; i < numOfN ; ++i )
109
+ result += maxFlowBetweenNodes [flowSource ][i ];
110
+ return result ;
111
+ }
112
+
113
+ /**
114
+ * Adds an Edge to the flow network
115
+ *
116
+ * @param fromNode
117
+ * is the starting node of an edge
118
+ * @param toNode
119
+ * is the ending node of an edge
120
+ * @param edgeCapacity
121
+ * represents edge capacity used for the capacity function which
122
+ * calculates the flow
123
+ */
124
+ public void addEdge (int fromNode , int toNode , long edgeCapacity ) {
125
+ assert edgeCapacity >= 0 ;
126
+ this .edgeCapacity [fromNode ][toNode ] += edgeCapacity ;
127
+ }
128
+
129
+ /**
130
+ * main function to present the output for characters and integers
131
+ *
132
+ * @param args
133
+ */
134
+ public static void main (String [] args ) {
135
+
136
+ // test 1 with integer input
137
+ System .out .println ("Test:" );
138
+ EdmondsKarpMaxFlow edmondsKarpTest = new EdmondsKarpMaxFlow (7 , 9 );
139
+ edmondsKarpTest .addEdge (0 , 3 , 3 );
140
+ edmondsKarpTest .addEdge (0 , 1 , 3 );
141
+ edmondsKarpTest .addEdge (1 , 2 , 4 );
142
+ edmondsKarpTest .addEdge (2 , 0 , 3 );
143
+ edmondsKarpTest .addEdge (2 , 3 , 1 );
144
+ edmondsKarpTest .addEdge (2 , 4 , 2 );
145
+ edmondsKarpTest .addEdge (3 , 4 , 2 );
146
+ edmondsKarpTest .addEdge (4 , 1 , 1 );
147
+ edmondsKarpTest .addEdge (4 , 6 , 1 );
148
+ System .out .println ("The maximum flow from flowSource to flowTarget is " + (edmondsKarpTest .getMaxFlow (1 , 4 )) + "." );
149
+ }
150
+ }
0 commit comments