#include<bits/stdc++.h> #define ll long long // Alternative for Dinic // Pros: support large number of vertices and edges // Cons: Take longer time to run. // Usage: // Dinic dinic; // dinic.init(n); // dinic.addEdge(...); // maxFlow = dinic.run(source, sink); struct Dinic2 { struct Edge { int v; // the other-end of this edge ll c; // capacity ll flow; // current flow int rev; // index of the reverse-edge }; int n; vector<Edge> *adj; int *dlevel; pair<int, int> *prev; int *visit; ll maxCapacity; Dinic2(){ maxCapacity = 1ll * oo * oo; } void init(int n_) { n = n_; adj = new vector<Edge>[n+1]; dlevel = new int[n+1]; prev = new pair<int, int> [n+1]; visit = new int[n+1]; fill(dlevel, dlevel + n+1, 0); fill(prev, prev + n+1, make_pair(0, 0)); fill(visit, visit + n+1, 0); } void addEdge(int u, int v, int w) { Edge e1{v, w, 0, adj[v].size()}; Edge e2{u, w, w, adj[u].size()}; adj[u].push_back(e1); adj[v].push_back(e2); } bool constructLevel(int source, int sink) { fill(dlevel, dlevel + n+1, -1); dlevel[source] = 0; queue<int> que; que.push(source); while(!que.empty()) { int vertex = que.front(); que.pop(); for (int i = 0; i < adj[vertex].size(); ++i) { int next = adj[vertex][i].v; if (dlevel[next] >= 0) continue; if (adj[vertex][i].c > adj[vertex][i].flow) { que.push(next); dlevel[next] = dlevel[vertex] + 1; } } } return dlevel[sink] >= 0; } ll makeFlow(int source, int sink) { ll ret = 0; fill(visit, visit + n+1, 0); stack<int> stk; stk.push(source); while(!stk.empty()) { int now = stk.top(); if (now != sink) { for (int i = 0; i < adj[now].size() && stk.top() == now; ++i) { int next = adj[now][i].v; if (dlevel[next] != dlevel[now] + 1 || visit[next]) continue; if (adj[now][i].c > adj[now][i].flow) { stk.push(next); prev[next] = {now, i}; } } if (stk.top() == now) { stk.pop(); visit[now] = 1; } } else { // now == sink ll f = maxCapacity, bottleneck; for (int cur = sink; cur != source; cur = abs(prev[cur].first)) { Edge &e = adj[prev[cur].first][prev[cur].second]; f = min(f, e.c - e.flow); } for (int cur = sink; cur != source; cur = abs(prev[cur].first)) { Edge &e = adj[prev[cur].first][prev[cur].second]; e.flow += f; Edge &e2 = adj[cur][e.rev]; e2.flow -= f; if (e.c == e.flow) bottleneck = prev[cur].first; } ret += f; while(!stk.empty() && stk.top() != bottleneck) stk.pop(); } } return ret; } ll run(int source, int sink) { ll maxFlow = 0; while (constructLevel(source, sink)) { maxFlow += makeFlow(source, sink); } return maxFlow; } };