1+ #include " ../Headers/0003_Graph/0018_MaximumFlowGoldbergGenericPushRelabel.h"
2+ #include < climits>
3+ using namespace std ;
4+
5+ namespace MaximumFlowGoldbergGenericPushRelabel
6+ {
7+ // Graph Private Member Methods
8+
9+ // Initializes Pre-Flow in the given Flow Network
10+ void Graph::InitializePreflow ()
11+ {
12+ // The height of source is set to highest possible height value
13+ this ->_height [this ->_source ] = this ->_noOfVertices ;
14+
15+ // Iterating over all the vertices
16+ for (int i = 0 ; i < this ->_noOfVertices ; i++)
17+ {
18+ // For the all the edges (source, v)
19+ if (this ->_residualGraph [this ->_source ][i] > 0 )
20+ {
21+ // v.excessFlow = capacity(source, v)
22+ this ->_excessFlow [i] = this ->_residualGraph [this ->_source ][i];
23+
24+ // source.excessFlow = source.excessFlow - capacity(source, v)
25+ this ->_excessFlow [this ->_source ] = this ->_excessFlow [this ->_source ] - this ->_residualGraph [this ->_source ][i];
26+
27+ // Adjusting the flow and reverse flow along source->v and v->source respectively
28+ this ->_residualGraph [i][this ->_source ] = this ->_residualGraph [this ->_source ][i];
29+ this ->_residualGraph [this ->_source ][i] = 0 ;
30+ }
31+ }
32+ }
33+
34+ // Checks if there is any vertex which has excess flow
35+ bool Graph::CheckOverFlow ()
36+ {
37+ // Iterating over all of the vertices
38+ for (int i = 0 ; i < this ->_noOfVertices ; i++)
39+ {
40+ // Checks if the current vertex is not any special vertex like source, sink
41+ // and also if there is excess flow in the current vertex and it is already not present in the queue
42+ if (i!=this ->_source && i!=this ->_sink && this ->_excessFlow [i] > 0 && this ->_visited [i] == false )
43+ {
44+ // Insert the current vertex into the queue
45+ this ->_nodeQueue .push (i);
46+
47+ // Mark it as visited, so until it leaves the queue it is not inserted again even if all the excess flow is neutralized
48+ this ->_visited [i] = true ;
49+ }
50+ }
51+
52+ // Checks if there is no vertex having excess flow then returns false
53+ if (this ->_nodeQueue .empty ())
54+ {
55+ return false ;
56+ }
57+
58+ return true ;
59+ }
60+
61+ // Pushes the flow from nodeU to its neighbour vertices
62+ bool Graph::Push (int nodeU)
63+ {
64+ int nodeV = -1 ;
65+ int minimumFlow = INT_MAX;
66+
67+ // Iterating over all the vertices
68+ for (int i = 0 ; i < this ->_noOfVertices ; i++)
69+ {
70+ // For G'.Adj[nodeU] select the vertex if edge (nodeU, i) is non-saturated and height[nodeU] == height[i] + 1
71+ if (this ->_residualGraph [nodeU][i] > 0 && this ->_height [nodeU] == this ->_height [i] + 1 )
72+ {
73+ nodeV = i;
74+ break ;
75+ }
76+ }
77+
78+ // Checks if any neighbour vertex found having non-saturated edge
79+ if (nodeV != -1 )
80+ {
81+ // Calculate the flow amount to be added along the edge and excess flow subtracted from nodeU
82+ minimumFlow = min (this ->_residualGraph [nodeU][nodeV], this ->_excessFlow [nodeU]);
83+
84+ // Adjust the flow and the reverse flow along (nodeU, nodeV)
85+ this ->_residualGraph [nodeU][nodeV] = this ->_residualGraph [nodeU][nodeV] - minimumFlow;
86+ this ->_residualGraph [nodeV][nodeU] = this ->_residualGraph [nodeV][nodeU] + minimumFlow;
87+
88+ // Adjust the excess flows in nodeU and nodeV
89+ this ->_excessFlow [nodeU] = this ->_excessFlow [nodeU] - minimumFlow;
90+ this ->_excessFlow [nodeV] = this ->_excessFlow [nodeV] + minimumFlow;
91+
92+ // Return that the Push operation is successful
93+ return true ;
94+ }
95+
96+ // Return that the Push operation is not successful
97+ return false ;
98+ }
99+
100+ // Relabels height of vertex nodeU when there are outgoing non-saturated edges available
101+ void Graph::Relabel (int nodeU)
102+ {
103+ int minimumHeight = INT_MAX;
104+
105+ // Iterating over all the vertices
106+ for (int nodeV = 0 ; nodeV < this ->_noOfVertices ; nodeV++)
107+ {
108+ // For G'.Adj[nodeU] select for which nodeV, height[nodeU] <= height[nodeV]
109+ if (this ->_residualGraph [nodeU][nodeV] > 0 && this ->_height [nodeU] <= this ->_height [nodeV])
110+ {
111+ // Get the minimum height among all these G'.Adj[nodeU]
112+ minimumHeight = min (minimumHeight, this ->_height [nodeV]);
113+ }
114+ }
115+
116+ // Set height[nodeU]
117+ this ->_height [nodeU] = minimumHeight + 1 ;
118+ }
119+
120+
121+ // Graph Public Member Methods
122+ void Graph::CreateGraph (int noOfVertices)
123+ {
124+ this ->_noOfVertices = noOfVertices;
125+ this ->_source = 0 ;
126+ this ->_sink = this ->_noOfVertices - 1 ;
127+ this ->_maximumFlow = 0 ;
128+ this ->_adjMatrix = vector<vector<int >>(this ->_noOfVertices , vector<int >(this ->_noOfVertices , 0 ));
129+ this ->_excessFlow = vector<int >(this ->_noOfVertices , 0 );
130+ this ->_height = vector<int >(this ->_noOfVertices , 0 );
131+ this ->_visited = vector<bool >(this ->_noOfVertices , false );
132+ }
133+
134+ void Graph::PushDirectedEdge (int valueU, int valueV, int capacity)
135+ {
136+ this ->_adjMatrix [valueU][valueV] = capacity;
137+ }
138+
139+ int Graph::FindMaximumFlowGoldbergGenericPushRelabel ()
140+ {
141+ this ->_residualGraph = this ->_adjMatrix ;
142+
143+ // Initialize Pre-flow
144+ this ->InitializePreflow ();
145+
146+ // Checks if there is some vertices which have excess flow
147+ while (this ->CheckOverFlow ())
148+ {
149+ // Get the vertex
150+ int nodeU = this ->_nodeQueue .front ();
151+
152+ // Checks if the Push operation is successful
153+ if (this ->Push (nodeU))
154+ {
155+ // Then remove the vertex from queue and set visited[nodeU] = true
156+ // so that on next CheckOverFlow() method call this vertex can be discovered if it still has some excess flow
157+ this ->_nodeQueue .pop ();
158+ this ->_visited [nodeU] = false ;
159+ }
160+
161+ // If the Push operation is not successful
162+ else
163+ {
164+ // Then Relabel nodeU without removing it from the queue
165+ this ->Relabel (nodeU);
166+ }
167+ }
168+
169+ // Return the excess flow in the sink vertex which is actually the maximum flow along the given flow network
170+ return this ->_excessFlow [this ->_sink ];
171+ }
172+ }
0 commit comments