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