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