-
Notifications
You must be signed in to change notification settings - Fork 0
/
MaxFlow - Push Relabel [V^3].cpp
135 lines (116 loc) · 2.9 KB
/
MaxFlow - Push Relabel [V^3].cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//Push-Relabel Algorithm for Flows - Gap Heuristic, Complexity: O(V^3)
//To obtain the actual flow values, look at all edges with capacity > 0
//Zero capacity edges are residual edges
struct edge
{
int from, to, cap, flow, index;
edge(int from, int to, int cap, int flow, int index):
from(from), to(to), cap(cap), flow(flow), index(index) {}
};
struct PushRelabel
{
int n;
vector<vector<edge> > g;
vector<long long> excess;
vector<int> height, active, count;
queue<int> Q;
PushRelabel(int n):
n(n), g(n), excess(n), height(n), active(n), count(2*n) {}
void addEdge(int from, int to, int cap)
{
g[from].push_back(edge(from, to, cap, 0, g[to].size()));
if(from==to)
g[from].back().index++;
g[to].push_back(edge(to, from, 0, 0, g[from].size()-1));
}
void enqueue(int v)
{
if(!active[v] && excess[v] > 0)
{
active[v]=true;
Q.push(v);
}
}
void push(edge &e)
{
int amt=(int)min(excess[e.from], (long long)e.cap - e.flow);
if(height[e.from]<=height[e.to] || amt==0)
return;
e.flow += amt;
g[e.to][e.index].flow -= amt;
excess[e.to] += amt;
excess[e.from] -= amt;
enqueue(e.to);
}
void relabel(int v)
{
count[height[v]]--;
int d=2*n;
for(auto &it:g[v])
{
if(it.cap-it.flow>0)
d=min(d, height[it.to]+1);
}
height[v]=d;
count[height[v]]++;
enqueue(v);
}
void gap(int k)
{
for(int v=0;v<n;v++)
{
if(height[v]<k)
continue;
count[height[v]]--;
height[v]=max(height[v], n+1);
count[height[v]]++;
enqueue(v);
}
}
void discharge(int v)
{
for(int i=0; excess[v]>0 && i<g[v].size(); i++)
push(g[v][i]);
if(excess[v]>0)
{
if(count[height[v]]==1)
gap(height[v]);
else
relabel(v);
}
}
long long max_flow(int source, int dest)
{
count[0] = n-1;
count[n] = 1;
height[source] = n;
active[source] = active[dest] = 1;
for(auto &it:g[source])
{
excess[source]+=it.cap;
push(it);
}
while(!Q.empty())
{
int v=Q.front();
Q.pop();
active[v]=false;
discharge(v);
}
long long max_flow=0;
for(auto &e:g[source])
max_flow+=e.flow;
return max_flow;
}
};
//Original Source: https://github.com/jaehyunp/stanfordacm/blob/master/code/PushRelabel.cc
//Problem 1: http://codeforces.com/contest/546/problem/E
//Solution 1: http://codeforces.com/contest/546/submission/40660003
//Problem 2: http://codeforces.com/contest/653/problem/D
//Solution 2: http://codeforces.com/contest/653/submission/40659969
//Problem 3 (Vertex Disjoint Chain with Path Printing): (K) http://codeforces.com/gym/101606/attachments/download/6242/2017-united-kingdom-ireland-programming-contest-ukiepc-2017-en.pdf
//Solution 3: http://codeforces.com/gym/101606/submission/41992537
//Problem 4: (Mincut = Maxflow) http://codeforces.com/gym/100733/problem/I
//Solution 4: http://codeforces.com/gym/100733/submission/41993711
//Problem 5: (Mincut on N plans): https://wcipeg.com/problem/noi06p4
//Solution 5: http://p.ip.fi/KQt0