forked from Punyaslok/snippets
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dinic.cpp
80 lines (68 loc) · 2.08 KB
/
dinic.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
// Network flow (Dinic's algorithm)
//
// Given a directed weighted graph, source, and sink, computes the maximum flow
// from source to sink.
//
// To use, call init(n), then add edges using edge(x, y, c1, c2), and finally
// call run(src, sink).
//
// To get the min-cut, check the dist[]. An edge (x, y) is a cut iff dist[x] != -1
// and dist[y] == -1.
//
// Functions:
// - init(n) initializes the algorithm with the given number of nodes
// - edge(x, y, c1, c2) adds edges x->y of capacity c1 and y->x of capacity c2
// - run(src, sink) runs the algorithm and returns the total flow
//
// Time complexity: O(V^2 * E)
//
// Constants to configure:
// - MAXV is the maximum number of vertices
// - MAXE is the maximum number of edges (i.e. twice the calls to function edge)
// - oo is the "infinity" value
namespace Dinic {
const int MAXV = 1000100;
const int MAXE = 1000100;
const llint oo = 1e18;
int V, E;
int last[MAXV], dist[MAXV], curr[MAXV];
int next[MAXE], adj[MAXE]; llint cap[MAXE];
void init(int n) {
V = n;
E = 0;
REP(i, V) last[i] = -1;
}
void edge(int x, int y, llint c1, llint c2) {
adj[E] = y; cap[E] = c1; next[E] = last[x]; last[x] = E++;
adj[E] = x; cap[E] = c2; next[E] = last[y]; last[y] = E++;
}
llint push(int x, int sink, llint flow) {
if (x == sink) return flow;
for (int &e = curr[x]; e != -1; e = next[e]) {
int y = adj[e];
if (cap[e] && dist[x] + 1 == dist[y])
if (llint f = push(y, sink, min(flow, cap[e])))
return cap[e] -= f, cap[e^1] += f, f;
}
return 0;
}
llint run(int src, int sink) {
llint ret = 0;
for (;;) {
REP(i, V) curr[i] = last[i];
REP(i, V) dist[i] = -1;
queue<int> Q;
Q.push(src), dist[src] = 0;
while (!Q.empty()) {
int x = Q.front(); Q.pop();
for (int e = last[x]; e != -1; e = next[e]) {
int y = adj[e];
if (cap[e] && dist[y] == -1) Q.push(y), dist[y] = dist[x] + 1;
}
}
if (dist[sink] == -1) break;
while (llint f = push(src, sink, oo)) ret += f;
}
return ret;
}
}