Skip to content

Commit 82436f1

Browse files
committed
feature-test: 0019 max flow relabel to front
1 parent 78ad19c commit 82436f1

File tree

7 files changed

+219
-2
lines changed

7 files changed

+219
-2
lines changed

Headers/0003_Graph/0018_MaximumFlowGoldbergGenericPushRelabel.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#pragma once
22

3-
#include<map>
43
#include<vector>
54
#include<queue>
65
using namespace std;
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+
}

SourceCodes/0003_Graph/0018_MaximumFlowGoldbergGenericPushRelabel.cc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#include "../Headers/0003_Graph/0018_MaximumFlowGoldbergGenericPushRelabel.h"
2-
#include<queue>
32
#include<climits>
43
using namespace std;
54

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#include "../Headers/0003_Graph/0019_MaximumFlowRelabelToFront.h"
2+
#include<climits>
3+
#include<iterator>
4+
using namespace std;
5+
6+
namespace MaximumFlowRelabelToFront
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+
void Graph::Discharge(int nodeU)
36+
{
37+
while (this->_excessFlow[nodeU] > 0)
38+
{
39+
bool hasPushed = false;
40+
for (int nodeV = 0; nodeV < this->_noOfVertices; nodeV++)
41+
{
42+
if (this->_residualGraph[nodeU][nodeV] > 0 && this->_height[nodeU] == 1 + this->_height[nodeV])
43+
{
44+
this->Push(nodeU, nodeV);
45+
hasPushed = true;
46+
if (this->_excessFlow[nodeU] == 0)
47+
{
48+
break;
49+
}
50+
}
51+
}
52+
53+
if (!hasPushed)
54+
{
55+
this->Relabel(nodeU);
56+
}
57+
}
58+
}
59+
60+
// Pushes the flow from nodeU to its neighbour vertices
61+
void Graph::Push(int nodeU, int nodeV)
62+
{
63+
// Calculate the flow amount to be added along the edge and excess flow subtracted from nodeU
64+
int minimumFlow = min(this->_residualGraph[nodeU][nodeV], this->_excessFlow[nodeU]);
65+
66+
// Adjust the flow and the reverse flow along (nodeU, nodeV)
67+
this->_residualGraph[nodeU][nodeV] = this->_residualGraph[nodeU][nodeV] - minimumFlow;
68+
this->_residualGraph[nodeV][nodeU] = this->_residualGraph[nodeV][nodeU] + minimumFlow;
69+
70+
// Adjust the excess flows in nodeU and nodeV
71+
this->_excessFlow[nodeU] = this->_excessFlow[nodeU] - minimumFlow;
72+
this->_excessFlow[nodeV] = this->_excessFlow[nodeV] + minimumFlow;
73+
74+
}
75+
76+
// Relabels height of vertex nodeU when there are outgoing non-saturated edges available
77+
void Graph::Relabel(int nodeU)
78+
{
79+
int minimumHeight = INT_MAX;
80+
81+
// Iterating over all the vertices
82+
for (int nodeV = 0; nodeV < this->_noOfVertices; nodeV++)
83+
{
84+
// For G'.Adj[nodeU] select for which nodeV, height[nodeU] <= height[nodeV]
85+
if (this->_residualGraph[nodeU][nodeV] > 0 && this->_height[nodeU] <= this->_height[nodeV])
86+
{
87+
// Get the minimum height among all these G'.Adj[nodeU]
88+
minimumHeight = min(minimumHeight, this->_height[nodeV]);
89+
}
90+
}
91+
92+
// Set height[nodeU]
93+
this->_height[nodeU] = minimumHeight + 1;
94+
}
95+
96+
97+
// Graph Public Member Methods
98+
void Graph::CreateGraph(int noOfVertices)
99+
{
100+
this->_noOfVertices = noOfVertices;
101+
this->_source = 0;
102+
this->_sink = this->_noOfVertices - 1;
103+
this->_maximumFlow = 0;
104+
this->_adjMatrix = vector<vector<int>>(this->_noOfVertices, vector<int>(this->_noOfVertices, 0));
105+
this->_excessFlow = vector<int>(this->_noOfVertices, 0);
106+
this->_height = vector<int>(this->_noOfVertices, 0);
107+
this->_visited = vector<bool>(this->_noOfVertices, false);
108+
}
109+
110+
void Graph::PushDirectedEdge(int valueU, int valueV, int capacity)
111+
{
112+
this->_adjMatrix[valueU][valueV] = capacity;
113+
}
114+
115+
int Graph::FindMaximumFlowRelabelToFront()
116+
{
117+
this->_residualGraph = this->_adjMatrix;
118+
119+
// Initialize Pre-flow
120+
this->InitializePreflow();
121+
122+
for (int i = 0; i < this->_noOfVertices; i++)
123+
{
124+
if (i != this->_source && i != this->_sink)
125+
{
126+
this->_nodeList.push_back(i);
127+
}
128+
}
129+
130+
list<int>::iterator nodeUiterator = this->_nodeList.begin();
131+
132+
while (nodeUiterator != this->_nodeList.end())
133+
{
134+
int oldHeight = this->_height[*nodeUiterator];
135+
this->Discharge(*nodeUiterator);
136+
if (this->_height[*nodeUiterator] > oldHeight)
137+
{
138+
this->_nodeList.splice(this->_nodeList.begin(), this->_nodeList, nodeUiterator);
139+
nodeUiterator++;
140+
}
141+
else
142+
{
143+
nodeUiterator++;
144+
}
145+
}
146+
147+
// Return the excess flow in the sink vertex which is actually the maximum flow along the given flow network
148+
return this->_excessFlow[this->_sink];
149+
}
150+
}

SourceCodes/0003_Graph/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ set(0003GRAPH_SOURCES
1818
0016_MaximumFlowEdmondsKarp.cc
1919
0017_MaximumBipartiteMatching.cc
2020
0018_MaximumFlowGoldbergGenericPushRelabel.cc
21+
0019_MaximumFlowRelabelToFront.cc
2122

2223
)
2324

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include<gtest/gtest.h>
2+
#include "../Headers/0003_Graph/0019_MaximumFlowRelabelToFront.h"
3+
#include "../0000_CommonUtilities/UnitTestHelper.h"
4+
using namespace std;
5+
6+
namespace MaximumFlowRelabelToFront
7+
{
8+
UnitTestHelper unitTestHelper;
9+
10+
TEST(MaximumFlowRelabelToFront, SimpleGraph)
11+
{
12+
// Arrange
13+
Graph graph;
14+
int noOfVertices = 6;
15+
int expectedMaximumFlow = 23;
16+
17+
18+
// Act
19+
graph.CreateGraph(noOfVertices);
20+
21+
graph.PushDirectedEdge(0, 1, 16);
22+
graph.PushDirectedEdge(0, 2, 13);
23+
graph.PushDirectedEdge(1, 3, 12);
24+
graph.PushDirectedEdge(2, 1, 4);
25+
graph.PushDirectedEdge(2, 4, 14);
26+
graph.PushDirectedEdge(3, 2, 9);
27+
graph.PushDirectedEdge(3, 5, 20);
28+
graph.PushDirectedEdge(4, 3, 7);
29+
graph.PushDirectedEdge(4, 5, 4);
30+
31+
int actualMaximumFlow = graph.FindMaximumFlowRelabelToFront();
32+
33+
// Assert
34+
ASSERT_EQ(expectedMaximumFlow, actualMaximumFlow);
35+
}
36+
}

Tests/0003_Graph/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ add_executable(
3030
0016_MaximumFlowEdmondsKarpTest.cc
3131
0017_MaximumBipartiteMatchingTest.cc
3232
0018_MaximumFlowGoldbergGenericPushRelabelTest.cc
33+
0019_MaximumFlowRelabelToFrontTest.cc
3334
)
3435

3536
target_link_libraries(

0 commit comments

Comments
 (0)