-
Notifications
You must be signed in to change notification settings - Fork 13
/
MaxFlow - Push Relabel [V^3]
132 lines (114 loc) · 2.8 KB
/
MaxFlow - Push Relabel [V^3]
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
//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