-
Notifications
You must be signed in to change notification settings - Fork 108
/
Copy pathPush Relabel.cpp
82 lines (70 loc) · 1.9 KB
/
Push Relabel.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
#define sz(x) (int)(x).size()
struct Edge {
int v;
ll flow, C;
int rev;
};
template <int SZ> struct PushRelabel {
vector<Edge> adj[SZ];
ll excess[SZ];
int dist[SZ], count[SZ+1], b = 0;
bool active[SZ];
vi B[SZ];
void addEdge(int u, int v, ll C) {
Edge a{v, 0, C, sz(adj[v])};
Edge b{u, 0, 0, sz(adj[u])};
adj[u].pb(a), adj[v].pb(b);
}
void enqueue (int v) {
if (!active[v] && excess[v] > 0 && dist[v] < SZ) {
active[v] = 1;
B[dist[v]].pb(v);
b = max(b, dist[v]);
}
}
void push (int v, Edge &e) {
ll amt = min(excess[v], e.C-e.flow);
if (dist[v] == dist[e.v]+1 && amt > 0) {
e.flow += amt, adj[e.v][e.rev].flow -= amt;
excess[e.v] += amt, excess[v] -= amt;
enqueue(e.v);
}
}
void gap (int k) {
FOR(v,1,SZ+1) if (dist[v] >= k) {
count[dist[v]] --;
dist[v] = SZ;
count[dist[v]] ++;
enqueue(v);
}
}
void relabel (int v) {
count[dist[v]] --; dist[v] = SZ;
for (auto e: adj[v]) if (e.C > e.flow) dist[v] = min(dist[v], dist[e.v] + 1);
count[dist[v]] ++;
enqueue(v);
}
void discharge(int v) {
for (auto &e: adj[v]) {
if (excess[v] > 0) push(v,e);
else break;
}
if (excess[v] > 0) {
if (count[dist[v]] == 1) gap(dist[v]);
else relabel(v);
}
}
ll maxFlow (int s, int t) {
for (auto &e: adj[s]) excess[s] += e.C;
count[0] = SZ;
enqueue(s); active[t] = 1;
while (b >= 0) {
if (sz(B[b])) {
int v = B[b].back(); B[b].pop_back();
active[v] = 0; discharge(v);
} else b--;
}
return excess[t];
}
};
PushRelabel<50000> network;