diff options
| author | Gloria Mundi <gloria@gloria-mundi.eu> | 2024-04-01 19:59:01 +0200 |
|---|---|---|
| committer | Gloria Mundi <gloria@gloria-mundi.eu> | 2024-04-01 19:59:01 +0200 |
| commit | 33343f96d94f2d7f12567b1c227e4e2399c8bd1b (patch) | |
| tree | 16b5ef80ee4605ce88410911fbb6beb6dfc1d7b2 /graph/pushRelabel.cpp | |
| parent | 4fc39dcd54243609febc1ce4c8a1470b3d31fd47 (diff) | |
| parent | 98aa28427350e72cb9abe4071c0c6b6870b7e6cc (diff) | |
merge mzuenni changes
Diffstat (limited to 'graph/pushRelabel.cpp')
| -rw-r--r-- | graph/pushRelabel.cpp | 151 |
1 files changed, 53 insertions, 98 deletions
diff --git a/graph/pushRelabel.cpp b/graph/pushRelabel.cpp index 52ba8b1..904aec6 100644 --- a/graph/pushRelabel.cpp +++ b/graph/pushRelabel.cpp @@ -1,109 +1,64 @@ -constexpr ll inf = 1ll<<60; - struct Edge { - int from, to; + int to, rev; ll f, c; }; -vector<Edge> edges; -vector<vector<int>> adj, llist; -vector<int> height, ccount, que; -vector<ll> excess; -vector<list<int>> dlist; -vector<list<int>::iterator> iter; -int highest, highestActive; - -void addEdge(int from, int to, ll c) { - adj[from].push_back(sz(edges)); - edges.push_back({from, to, 0, c}); - adj[to].push_back(sz(edges)); - edges.push_back({to, from, 0, 0}); -} +vector<vector<Edge>> adj; +vector<vector<int>> hs; +vector<ll> ec; +vector<int> cur, H; -void globalRelabel(int n, int t) { - height.assign(n, n); - height[t] = 0; - ccount.assign(n, 0); - que.assign(n+1, 0); - int qh = 0, qt = 0; - for (que[qt++] = t; qh < qt;) { - int v = que[qh++], h = height[v] + 1; - for (int id : adj[v]) { - if (height[edges[id].to] == n && edges[id ^ 1].c - edges[id ^ 1].f > 0) { - ccount[height[edges[id].to] = h]++; - que[qt++] = edges[id].to; - }}} - llist.assign(n+1, {}); - dlist.assign(n+1, {}); - for (int v = 0; v < n; v++) { - if (height[v] < n) { - iter[v] = dlist[height[v]].insert(dlist[height[v]].begin(), v); - if (excess[v] > 0) llist[height[v]].push_back(v); - }} - highest = highestActive = height[que[qt - 1]]; +void addEdge(int u, int v, ll c) { + adj[u].push_back({v, (int)sz(adj[v]), 0, c}); + adj[v].push_back({u, (int)sz(adj[u])-1, 0, 0}); } -void push(int v, int id) { - int u = edges[id].to; - ll df = min(excess[v], edges[id].c - edges[id].f); - edges[id].f += df; - edges[id^1].f -= df; - excess[v] -= df; - excess[u] += df; - if (0 < excess[u] && excess[u] <= df) llist[height[u]].push_back(u); +void addFlow(Edge& e, ll f) { + if (ec[e.to] == 0 && f > 0) + hs[H[e.to]].push_back(e.to); + e.f += f; + adj[e.to][e.rev].f -= f; + ec[e.to] += f; + ec[adj[e.to][e.rev].to] -= f; } -void discharge(int n, int v) { - int nh = n; - for (int id : adj[v]) { - if (edges[id].c - edges[id].f > 0) { - if (height[v] == height[edges[id].to] + 1) { - push(v, id); - if (!excess[v]) return; - } else { - nh = min(nh, height[edges[id].to] + 1); - }}} - int h = height[v]; - if (ccount[h] == 1) { - for (int i = h; i <= highest; i++) { - for (auto p : dlist[i]) --ccount[height[p]], height[p] = n; - dlist[i].clear(); - } - highest = h - 1; - } else { - --ccount[h], iter[v] = dlist[h].erase(iter[v]), height[v] = nh; - if (nh == n) return; - ++ccount[nh], iter[v] = dlist[nh].insert(dlist[nh].begin(), v); - highest = max(highest, highestActive = nh); - llist[nh].push_back(v); -}} - ll maxFlow(int s, int t) { int n = sz(adj); - llist.assign(n + 1, {}); - dlist.assign(n + 1, {}); - highestActive = highest = 0; - height.assign(n, 0); - height[s] = n; - iter.resize(n); - for (int v = 0; v < n; v++) { - if (v != s) iter[v] = dlist[height[v]].insert(dlist[height[v]].begin(), v); - } - ccount.assign(n, 0); - ccount[0] = n-1; - excess.assign(n, 0); - excess[s] = inf; - excess[t] = -inf; - for (int id : adj[s]) push(s, id); - globalRelabel(n, t); - while (highestActive >= 0) { - if (llist[highestActive].empty()) { - highestActive--; - continue; - } - int v = llist[highestActive].back(); - llist[highestActive].pop_back(); - discharge(n, v); - } - return excess[t] + inf; -} + hs.assign(2*n, {}); + ec.assign(n, 0); + cur.assign(n, 0); + H.assign(n, 0); + H[s] = n; + ec[t] = 1;//never set t to active... + vector<int> co(2*n); + co[0] = n - 1; + for (Edge& e : adj[s]) addFlow(e, e.c); + for (int hi = 0;;) { + while (hs[hi].empty()) if (!hi--) return -ec[s]; + int v = hs[hi].back(); + hs[hi].pop_back(); + while (ec[v] > 0) { + if (cur[v] == sz(adj[v])) { + H[v] = 2*n; + for (int i = 0; i < sz(adj[v]); i++) { + Edge& e = adj[v][i]; + if (e.c - e.f > 0 && + H[v] > H[e.to] + 1) { + H[v] = H[e.to] + 1; + cur[v] = i; + }} + co[H[v]]++; + if (!--co[hi] && hi < n) { + for (int i = 0; i < n; i++) { + if (hi < H[i] && H[i] < n) { + co[H[i]]--; + H[i] = n + 1; + }}} + hi = H[v]; + } else { + Edge& e = adj[v][cur[v]]; + if (e.c - e.f > 0 && H[v] == H[e.to] + 1) { + addFlow(adj[v][cur[v]], min(ec[v], e.c - e.f)); + } else { + cur[v]++; +}}}}} |
