-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathmax_flow_push.cpp
More file actions
92 lines (80 loc) · 2.33 KB
/
max_flow_push.cpp
File metadata and controls
92 lines (80 loc) · 2.33 KB
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
template<typename weight_t, int maxv>
struct PreflowMaxFlow {
const int S = maxv - 2;
const int T = maxv - 1;
int h[maxv];
weight_t e[maxv];
weight_t flow[maxv][maxv], cap[maxv][maxv];
vector<int> g[maxv];
int gpos[maxv];
void reset() {
memset(cap, 0, sizeof(cap));
for (int i = 0; i < maxv; ++i) g[i].clear();
memset(gpos, 0, sizeof(gpos));
}
void addDirectedEdge(int from, int to, weight_t ecap) {
assert(0 <= from && from < maxv);
assert(0 <= to && to < maxv);
cap[from][to] += ecap;
g[from].push_back(to);
g[to].push_back(from);
}
void push(int v, int u) { // push from v to u
weight_t d = min(e[v], cap[v][u] - flow[v][u]);
flow[v][u] += d;
flow[u][v] -= d;
e[v] -= d;
e[u] += d;
}
void lift(int v) { // up v
int besth = 0x3f3f3f3f;
for (int u : g[v]) if (flow[v][u] < cap[v][u])
besth = min(besth, h[u]);
assert(besth >= h[v]);
h[v] = besth + 1;
}
void discharge(int v) {
while (e[v]) {
if (gpos[v] == int(g[v].size())) {
lift(v);
gpos[v] = 0;
continue;
}
int u = g[v][gpos[v]];
if (flow[v][u] < cap[v][u] && h[v] == h[u] + 1)
push(v, u);
else
++gpos[v];
}
}
weight_t go() {
memset(h, 0, sizeof(h));
h[S] = maxv;
memset(e, 0, sizeof(e));
memset(flow, 0, sizeof(flow));
for (int i = 0; i < S; ++i) if (cap[S][i]) {
flow[S][i] = e[i] = cap[S][i];
flow[i][S] = -cap[S][i];
e[S] -= cap[i][S];
}
list<int> l;
for (int i = 0; i < S; ++i) l.push_back(i);
auto it = l.begin();
while (it != l.end()) {
int v = *it;
int prevh = h[v];
discharge(v);
if (h[v] > prevh) {
l.push_front(v);
l.erase(it);
it = l.begin();
}
++it;
}
weight_t res = 0;
for (int v = 0; v < S; ++v) {
res += flow[S][v];
}
return res;
}
};