summaryrefslogtreecommitdiff
path: root/graph/pushRelabel2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'graph/pushRelabel2.cpp')
-rw-r--r--graph/pushRelabel2.cpp143
1 files changed, 50 insertions, 93 deletions
diff --git a/graph/pushRelabel2.cpp b/graph/pushRelabel2.cpp
index 5619d88..7d7defd 100644
--- a/graph/pushRelabel2.cpp
+++ b/graph/pushRelabel2.cpp
@@ -1,17 +1,12 @@
-constexpr ll inf = 1ll<<60;
-
-struct edge {
+struct Edge {
int from, to;
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;
+vector<Edge> edges;
+vector<vector<int>> adj, hs;
+vector<ll> ec;
+vector<int> cur, H;
void addEdge(int from, int to, ll c) {
adj[from].push_back(sz(edges));
@@ -20,90 +15,52 @@ void addEdge(int from, int to, ll c) {
edges.push_back({to, from, 0, 0});
}
-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 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(int id, ll f) {
+ if (ec[edges[id].to] == 0 && f > 0)
+ hs[H[edges[id].to]].push_back(edges[id].to);
+ edges[id].f += f;
+ edges[id^1].f -= f;
+ ec[edges[id].to] += f;
+ ec[edges[id].from] -= 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[u];
- 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 (int id : adj[s]) addFlow(id, edges[id].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++) {
+ int id = adj[v][i];
+ if (edges[id].c - edges[id].f > 0 &&
+ H[v] > H[edges[id].to] + 1) {
+ H[v] = H[edges[id].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 {
+ auto e = edges[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]++;
+}}}}}