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