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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
| template <typename T> struct PushRelabel { const int inf = 0x3f3f3f3f; const T INF = 0x3f3f3f3f3f3f3f3f; struct Edge { int to, cap, flow, anti; Edge(int v = 0, int w = 0, int id = 0) : to(v), cap(w), flow(0), anti(id) {} }; vector<vector<Edge>> e; vector<vector<int>> gap; vector<T> ex; vector<bool> ingap; vector<int> h; int n, gobalcnt, maxH = 0; T maxflow = 0;
PushRelabel(int n) : n(n), e(n + 1), ex(n + 1), gap(n + 1) {} void addedge(int u, int v, int w) { e[u].push_back({v, w, (int)e[v].size()}); e[v].push_back({u, 0, (int)e[u].size() - 1}); } void PushEdge(int u, Edge &edge) { int v = edge.to, d = min(ex[u], 1LL * edge.cap - edge.flow); ex[u] -= d; ex[v] += d; edge.flow += d; e[v][edge.anti].flow -= d; if (h[v] != inf && d > 0 && ex[v] == d && !ingap[v]) { ++gobalcnt; gap[h[v]].push_back(v); ingap[v] = 1; } } void PushPoint(int u) { for (auto k = e[u].begin(); k != e[u].end(); k++) { if (h[k->to] + 1 == h[u] && k->cap > k->flow) { PushEdge(u, *k); if (!ex[u]) break; } } if (!ex[u]) return; if (gap[h[u]].empty()) { for (int i = h[u] + 1; i <= min(maxH, n); i++) { for (auto v : gap[i]) { ingap[v] = 0; } gap[i].clear(); } } h[u] = inf; for (auto [to, cap, flow, anti] : e[u]) { if (cap > flow) { h[u] = min(h[u], h[to] + 1); } } if (h[u] >= n) return; maxH = max(maxH, h[u]); if (!ingap[u]) { gap[h[u]].push_back(u); ingap[u] = 1; } } void init(int t, bool f = 1) { ingap.assign(n + 1, 0); for (int i = 1; i <= maxH; i++) { gap[i].clear(); } gobalcnt = 0, maxH = 0; queue<int> q; h.assign(n + 1, inf); h[t] = 0, q.push(t); while (q.size()) { int u = q.front(); q.pop(), maxH = h[u]; for (auto &[v, cap, flow, anti] : e[u]) { if (h[v] == inf && e[v][anti].cap > e[v][anti].flow) { h[v] = h[u] + 1; q.push(v); if (f) { gap[h[v]].push_back(v); ingap[v] = 1; } } } } } T work(int s, int t) { init(t, 0); if (h[s] == inf) return maxflow; h[s] = n; ex[s] = INF; ex[t] = -INF; for (auto k = e[s].begin(); k != e[s].end(); k++) { PushEdge(s, *k); } while (maxH > 0) { if (gap[maxH].empty()) { maxH--; continue; } int u = gap[maxH].back(); gap[maxH].pop_back(); ingap[u] = 0; PushPoint(u); if (gobalcnt >= 10 * n) { init(t); } } ex[s] -= INF; ex[t] += INF; return maxflow = ex[t]; } };
|