$dinic$
前向星建图,便于找反边(编号^$1$),$bfs$给图分层,让他只能流入更低的层,顺便判断出图是否已经阻断无法再流向汇点,$head$每次复制一份,复制出的那一份每次遍历过一条已经被阻塞的边,就直接跟着$next$改到直接指向下一条边,$bfs$时再重新改回初始状态,这是和复杂度的正确性有关的,防止在单点处被卡成$O(E^2)$,$dfs$返回值是这一次又松弛出多少流量。
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
| ll bfs() { queue<int> q; fp(i, 1, n * 2 * k) dep[i] = inf, nh[i] = head[i]; dep[s] = 0; q.push(s); while (!q.empty()) { ll x = q.front(); q.pop(); for (int i = head[x]; i; i = e[i].next) { if (e[i].w && dep[e[i].to] == inf) dep[e[i].to] = dep[x] + 1, q.push(e[i].to); } } // cout<<dep[t]<<endl; return dep[t] != inf; } ll dfs(ll x, ll fl) { // cout<<x<<endl; if (x == t) return fl; ll res = 0; for (ll& i = nh[x]; i && fl; i = e[i].next) { if (dep[e[i].to] == dep[x] + 1) { ll w = dfs(e[i].to, min(fl, e[i].w)); fl -= w; res += w; e[i].w -= w; e[i ^ 1].w += w; } } return res; } //主函数内 int main(){ while(bfs())ans+=dfs(); }
|
时间复杂度$O(V^2E)$