diff --git a/content/graph/Dinic.h b/content/graph/Dinic.h new file mode 100644 index 000000000..1693c118d --- /dev/null +++ b/content/graph/Dinic.h @@ -0,0 +1,50 @@ +/** + * Author: chilli + * Date: 2019-04-26 + * License: CC0 + * Source: https://cp-algorithms.com/graph/dinic.html + * Description: Flow algorithm with guaranteed complexity $O(V^2E)$. + * $O(\sqrt{V}E)$ for bipartite graphs, $O(\min(V^{1/2}, E^{2/3})E))$ for unit graphs. + * To obtain the actual flow, look at positive values only. + * Status: Tested on SPOJ FASTFLOW and SPOJ MATCHING + */ +struct Dinic { + struct Edge { + int to, rev; + ll c, f; + }; + vi lvl, ptr, q; + vector> adj; + Dinic(int n) : lvl(n), ptr(n), q(n), adj(n) {} + void addEdge(int a, int b, ll c, int rcap = 0) { + adj[a].push_back({b, sz(adj[b]), c, 0}); + adj[b].push_back({a, sz(adj[a]) - 1, rcap, 0}); + } + ll dfs(int v, int t, ll f) { + if (v == t || !f) return f; + for (int& i = ptr[v]; i < sz(adj[v]); i++) { + Edge& e = adj[v][i]; + if (lvl[e.to] == lvl[v] + 1) + if (ll p = dfs(e.to, t, min(f, e.c - e.f))) { + e.f += p, adj[e.to][e.rev].f -= p; + return p; + } + } + return 0; + } + ll calc(int s, int t) { + ll flow = 0; q[0] = s; + do { + lvl = ptr = vi(sz(q)); + int qi = 0, qe = lvl[s] = 1; + while (qi < qe && !lvl[t]) { + int v = q[qi++]; + trav(e, adj[v]) + if (!lvl[e.to] && e.f < e.c) + q[qe++] = e.to, lvl[e.to] = lvl[v] + 1; + } + while (ll p = dfs(s, t, LLONG_MAX)) flow += p; + } while (lvl[t]); + return flow; + } +}; diff --git a/content/graph/chapter.tex b/content/graph/chapter.tex index a9f9b1790..197db9e9e 100644 --- a/content/graph/chapter.tex +++ b/content/graph/chapter.tex @@ -12,6 +12,7 @@ \section{Network flow} \kactlimport{PushRelabel.h} \kactlimport{MinCostMaxFlow.h} \kactlimport{EdmondsKarp.h} + % \kactlimport{Dinic.h} \kactlimport{MinCut.h} \kactlimport{GlobalMinCut.h}