Skip to content

Commit 6814ba1

Browse files
authored
Merge pull request #64 from Debashis08/release
Release
2 parents 783145d + b4a2a15 commit 6814ba1

8 files changed

+478
-0
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#pragma once
2+
3+
#include<vector>
4+
#include<queue>
5+
using namespace std;
6+
7+
namespace MaximumFlowGoldbergGenericPushRelabel
8+
{
9+
class Graph
10+
{
11+
private:
12+
int _noOfVertices;
13+
int _source;
14+
int _sink;
15+
int _maximumFlow;
16+
vector<vector<int>> _adjMatrix;
17+
vector<vector<int>> _residualGraph;
18+
vector<int> _excessFlow;
19+
vector<int> _height;
20+
vector<bool> _visited;
21+
queue<int> _nodeQueue;
22+
void InitializePreflow();
23+
bool CheckOverFlow();
24+
bool Push(int nodeU);
25+
void Relabel(int nodeU);
26+
public:
27+
void CreateGraph(int noOfVertices);
28+
void PushDirectedEdge(int valueU, int valueV, int capacity);
29+
int FindMaximumFlowGoldbergGenericPushRelabel();
30+
};
31+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#pragma once
2+
3+
#include<vector>
4+
#include<list>
5+
using namespace std;
6+
7+
namespace MaximumFlowRelabelToFront
8+
{
9+
class Graph
10+
{
11+
private:
12+
int _noOfVertices;
13+
int _source;
14+
int _sink;
15+
int _maximumFlow;
16+
vector<vector<int>> _adjMatrix;
17+
vector<vector<int>> _residualGraph;
18+
vector<int> _excessFlow;
19+
vector<int> _height;
20+
vector<bool> _visited;
21+
list<int> _nodeList;
22+
void InitializePreflow();
23+
void Discharge(int nodeU);
24+
void Push(int nodeU, int nodeV);
25+
void Relabel(int nodeU);
26+
public:
27+
void CreateGraph(int noOfVertices);
28+
void PushDirectedEdge(int valueU, int valueV, int capacity);
29+
int FindMaximumFlowRelabelToFront();
30+
};
31+
}
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
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

Comments
 (0)