|
| 1 | +<snippet> |
| 2 | + <content><![CDATA[ |
| 3 | +template <typename T> |
| 4 | +class Max_flow { |
| 5 | +private: |
| 6 | + struct Edge { |
| 7 | + int v, u, idx; |
| 8 | + T c, f; |
| 9 | + }; |
| 10 | +
|
| 11 | + const int INF = 1e9; |
| 12 | + vector <vector <int>> gr; |
| 13 | + vector <Edge> e; |
| 14 | + vector <int> dst; |
| 15 | +
|
| 16 | + bool bfs(int s, int t) { |
| 17 | + dst = vector <int> (sz(gr), INF); |
| 18 | + dst[s] = 0; |
| 19 | + deque <int> q = {s}; |
| 20 | + while (!q.empty()) { |
| 21 | + int v = q.front(); |
| 22 | + q.pop_front(); |
| 23 | + for (int i : gr[v]) { |
| 24 | + int u = e[i].u; |
| 25 | + T c = e[i].c, f = e[i].f; |
| 26 | + if (c - f > 0 && dst[v] + 1 < dst[u]) { |
| 27 | + q.pb(u); |
| 28 | + dst[u] = dst[v] + 1; |
| 29 | + } |
| 30 | + } |
| 31 | + } |
| 32 | + return dst[t] < INF; |
| 33 | + } |
| 34 | +
|
| 35 | + vector <int> lst; |
| 36 | +
|
| 37 | + T dfs(int v, int t, T delta) { |
| 38 | + if (v == t || delta == 0) |
| 39 | + return delta; |
| 40 | + for (; lst[v] < sz(gr[v]); ++lst[v]) { |
| 41 | + int i = gr[v][lst[v]]; |
| 42 | + int u = e[i].u; |
| 43 | + T c = e[i].c, f = e[i].f; |
| 44 | + if (dst[u] == dst[v] + 1 && c - f > 0) { |
| 45 | + if (T cur_delta = dfs(u, t, min(delta, c - f))) { |
| 46 | + e[i].f += cur_delta; |
| 47 | + e[i ^ 1].f -= cur_delta; |
| 48 | + return cur_delta; |
| 49 | + } |
| 50 | + } |
| 51 | + } |
| 52 | + return 0; |
| 53 | + } |
| 54 | +
|
| 55 | + T find_path(int s, int t, vector <vector <int>>& paths) { |
| 56 | + vector <bool> used(sz(gr)); |
| 57 | + deque <int> edges; |
| 58 | + int v = s; |
| 59 | + while (!used[v] && v != t) { |
| 60 | + used[v] = true; |
| 61 | + int nxt = -1; |
| 62 | + for (int i : gr[v]) { |
| 63 | + int u = e[i].u; |
| 64 | + T f = e[i].f; |
| 65 | + if (f > 0) { |
| 66 | + nxt = i; |
| 67 | + break; |
| 68 | + } |
| 69 | + } |
| 70 | + if (nxt == -1) |
| 71 | + return 0; |
| 72 | + edges.pb(nxt); |
| 73 | + v = e[nxt].u; |
| 74 | + } |
| 75 | + if (used[v]) |
| 76 | + while (e[edges[0]].v != v) |
| 77 | + edges.pop_front(); |
| 78 | + T delta = numeric_limits<T>::max(); |
| 79 | + for (int i : edges) |
| 80 | + chkmin(delta, e[i].f); |
| 81 | + for (int i : edges) { |
| 82 | + e[i].f -= delta; |
| 83 | + e[i ^ 1].f += delta; |
| 84 | + } |
| 85 | + if (!used[v]) { |
| 86 | + paths.pb({}); |
| 87 | + paths.back().pb(e[0].v); |
| 88 | + for (auto i : edges) |
| 89 | + paths.back().pb(e[i].u); |
| 90 | + } |
| 91 | + return delta; |
| 92 | + } |
| 93 | +
|
| 94 | +public: |
| 95 | + Max_flow(int _n) { |
| 96 | + gr.resize(_n); |
| 97 | + } |
| 98 | +
|
| 99 | + T dinic(int s, int t) { |
| 100 | + T ans = 0; |
| 101 | + while (bfs(s, t)) { |
| 102 | + lst = vector <int> (sz(gr)); |
| 103 | + while (T cur = dfs(s, t, numeric_limits<T>::max())) |
| 104 | + ans += cur; |
| 105 | + } |
| 106 | + return ans; |
| 107 | + } |
| 108 | +
|
| 109 | + vector <vector <int>> decompose(int s, int t) { |
| 110 | + vector <vector <int>> paths; |
| 111 | + while (find_path(s, t, paths)); |
| 112 | + return paths; |
| 113 | + } |
| 114 | +
|
| 115 | + void add_edge(int v, int u, T c, int i = -1) { |
| 116 | + gr[v].pb(sz(e)); |
| 117 | + e.pb({v, u, i, c, 0}); |
| 118 | + gr[u].pb(sz(e)); |
| 119 | + e.pb({u, v, i, 0, 0}); |
| 120 | + } |
| 121 | +}; |
| 122 | +]]></content> |
| 123 | + <!-- Optional: Set a tabTrigger to define how to trigger the snippet --> |
| 124 | + <tabTrigger>DINIC</tabTrigger> |
| 125 | + <!-- Optional: Set a scope to limit where the snippet will trigger --> |
| 126 | + <scope>source.c++</scope> |
| 127 | +</snippet> |
0 commit comments