1
+ #include " ../Headers/0003_Graph/0016_MaximumFlowEdmondsKarp.h"
2
+ #include < climits>
3
+ #include < queue>
4
+ using namespace std ;
5
+
6
+ namespace MaximumFlowEdmondsKarp
7
+ {
8
+ // Graph Private Member Methods
9
+ void Graph::ResolveAntiParallelEdges ()
10
+ {
11
+ int countParallelEdges = 0 ;
12
+ for (int i = 0 ; i < this ->_noOfVertices ; i++)
13
+ {
14
+ for (int j = 0 ; j < this ->_noOfVertices ; j++)
15
+ {
16
+ if (this ->_adjMatrix [i][j] > 0 && this ->_adjMatrix [j][i] > 0 )
17
+ {
18
+ countParallelEdges++;
19
+ }
20
+ }
21
+ }
22
+
23
+ // As i->j and j->i both edges has been counted, actual count is count = count / 2
24
+ countParallelEdges /= 2 ;
25
+
26
+ this ->_flagParallelEdges = countParallelEdges > 0 ;
27
+
28
+ // If there are no anti-parallel edges, no need to modify the adjMatrix
29
+ if (!this ->_flagParallelEdges )
30
+ {
31
+ return ;
32
+ }
33
+
34
+ int newNoOfVertices = this ->_noOfVertices + countParallelEdges;
35
+
36
+ // Modifying the adjMatrix
37
+ for (auto & edge : this ->_adjMatrix )
38
+ {
39
+ edge.resize (newNoOfVertices, 0 );
40
+ }
41
+ int k = this ->_noOfVertices ;
42
+ this ->_visited .resize (newNoOfVertices, false );
43
+ this ->_parent .resize (newNoOfVertices, -1 );
44
+ this ->_adjMatrix .resize (newNoOfVertices, vector<int >(newNoOfVertices, 0 ));
45
+
46
+ // Removing the anti-parallel edges by adding new nodes
47
+ for (int i = 0 ; i < this ->_noOfVertices ; i++)
48
+ {
49
+ for (int j = 0 ; j < this ->_noOfVertices ; j++)
50
+ {
51
+ if (this ->_adjMatrix [i][j] > 0 && this ->_adjMatrix [j][i] > 0 )
52
+ {
53
+ this ->_adjMatrix [i][k] = this ->_adjMatrix [i][j];
54
+ this ->_adjMatrix [k][j] = this ->_adjMatrix [i][j];
55
+ this ->_adjMatrix [i][j] = 0 ;
56
+ k++;
57
+ }
58
+ }
59
+ }
60
+
61
+ // Updating the total no of vertices after modifying the adjMatrix
62
+ this ->_noOfVertices = newNoOfVertices;
63
+ }
64
+
65
+ bool Graph::BreadthFirstSearch ()
66
+ {
67
+ // Resetting the visited values
68
+ fill (this ->_visited .begin (), this ->_visited .end (), false );
69
+
70
+ // Resetting the parent values
71
+ fill (this ->_parent .begin (), this ->_parent .end (), -1 );
72
+
73
+ queue<int > nodeQueue;
74
+ nodeQueue.push (this ->_source );
75
+ this ->_visited [this ->_source ] = true ;
76
+
77
+ while (!nodeQueue.empty ())
78
+ {
79
+ int nodeU = nodeQueue.front ();
80
+ nodeQueue.pop ();
81
+
82
+ for (int nodeV = 0 ; nodeV < this ->_noOfVertices ; nodeV++)
83
+ {
84
+ if (!this ->_visited [nodeV] && this ->_residualGraph [nodeU][nodeV] > 0 )
85
+ {
86
+ this ->_parent [nodeV] = nodeU;
87
+ this ->_visited [nodeV] = true ;
88
+ nodeQueue.push (nodeV);
89
+ }
90
+ }
91
+ }
92
+
93
+ // Returning the visited value of the sink vertex, initially it was set to false
94
+ return this ->_visited [this ->_sink ];
95
+ }
96
+
97
+ // Graph Public Member Methods
98
+ void Graph::CreateGraph (int noOfVertices)
99
+ {
100
+ this ->_noOfVertices = noOfVertices;
101
+ this ->_source = 0 ;
102
+ this ->_sink = this ->_noOfVertices - 1 ;
103
+ this ->_maximumFlow = 0 ;
104
+ this ->_flagParallelEdges = false ;
105
+ this ->_adjMatrix = vector<vector<int >>(this ->_noOfVertices , vector<int >(this ->_noOfVertices , 0 ));
106
+ this ->_parent = vector<int >(this ->_noOfVertices , -1 );
107
+ this ->_visited = vector<bool >(this ->_noOfVertices , false );
108
+ }
109
+
110
+ void Graph::PushDirectedEdge (int valueU, int valueV, int capacity)
111
+ {
112
+ this ->_adjMatrix [valueU][valueV] = capacity;
113
+ }
114
+
115
+ int Graph::FindMaximumFlowEdmondsKarp ()
116
+ {
117
+ // Resolving all the parallel edges if present
118
+ this ->ResolveAntiParallelEdges ();
119
+ this ->_residualGraph = this ->_adjMatrix ;
120
+
121
+ // While there exists a path p from source to sink in the residual network G'
122
+ while (this ->BreadthFirstSearch ())
123
+ {
124
+ int augmentedPathFlow = INT_MAX;
125
+
126
+ // Calculating c'(p) = min{ c'(u,v) : (u,v) is in p }
127
+ for (int nodeV = this ->_sink ; nodeV > this ->_source ; nodeV = this ->_parent [nodeV])
128
+ {
129
+ int nodeU = this ->_parent [nodeV];
130
+ augmentedPathFlow = min (augmentedPathFlow, this ->_residualGraph [nodeU][nodeV]);
131
+ }
132
+
133
+ for (int nodeV = this ->_sink ; nodeV > this ->_source ; nodeV = this ->_parent [nodeV])
134
+ {
135
+ int nodeU = this ->_parent [nodeV];
136
+ this ->_residualGraph [nodeU][nodeV] -= augmentedPathFlow;
137
+ this ->_residualGraph [nodeV][nodeU] += augmentedPathFlow;
138
+ }
139
+ this ->_maximumFlow += augmentedPathFlow;
140
+ }
141
+
142
+ return this ->_maximumFlow ;
143
+ }
144
+ }
0 commit comments