summaryrefslogtreecommitdiff
path: root/graph
diff options
context:
space:
mode:
authorNoobie99 <noob999noob999@gmail.com>2023-08-29 10:09:15 +0200
committerNoobie99 <noob999noob999@gmail.com>2023-08-29 10:09:15 +0200
commit911a19c17730d912f5e64e2b8bcc28980a956b8e (patch)
tree64992136de00e875043733e9c94fe3efc84336bc /graph
parent10df00ff808c6681c31ff115e53fcaafa17d96d1 (diff)
remove 1 pushrelabel + consistency
Diffstat (limited to 'graph')
-rw-r--r--graph/pushRelabel.cpp158
-rw-r--r--graph/pushRelabel2.cpp143
-rw-r--r--graph/pushRelabel3.cpp66
3 files changed, 147 insertions, 220 deletions
diff --git a/graph/pushRelabel.cpp b/graph/pushRelabel.cpp
index da3ada7..52ba8b1 100644
--- a/graph/pushRelabel.cpp
+++ b/graph/pushRelabel.cpp
@@ -1,73 +1,109 @@
-struct PushRelabel {
- vector<vector<ll>> capacitie, flow;
- vector<ll> excess;
- vector<int> height, seen, list;
- int n;
+constexpr ll inf = 1ll<<60;
- PushRelabel(int n) {
- this->n = n;
- capacities.assign(n, vector<ll>(n));
- flow.assign(n, vector<ll>(n));
- excess.assign(n, 0);
- height.assign(n, 0);
- seen.assign(n, 0);
- list.assign(n - 2, 0);
- }
+struct Edge {
+ int from, to;
+ ll f, c;
+};
- inline void addEdge(int u, int v, ll c) {capacities[u][v] += 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 push(int u, int v) {
- ll send = min(excess[u], capacities[u][v] - flow[u][v]);
- flow[u][v] += send; flow[v][u] -= send;
- excess[u] -= send; excess[v] += send;
- }
+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});
+}
- void relabel(int v) {
- int minHeight = INT_INF;
- for (int u = 0; u < n; u++) {
- if (capacities[v][u] - flow[v][u] > 0) {
- minHeight = min(minHeight, height[u]);
- height[v] = minHeight + 1;
+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 discharge(int v) {
- while (excess[v] > 0) {
- if (seen[v] < n) {
- int u = seen[v];
- if (capacities[v][u] - flow[v][u] > 0 && height[v] > height[u]) {
- push(v, u);
- } else seen[v]++;
+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 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 {
- relabel(v);
- seen[v] = 0;
+ 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);
+}}
- void moveToFront(int v) {
- int temp = list[v];
- for (int u = v; u > 0; u--) list[u] = list[u - 1];
- list[0] = temp;
+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);
}
-
- ll maxFlow(int source, int target) {
- for (int v = 0, p = 0; v < n; v++)
- if (v != source && v != target) list[p++] = v;
-
- height[source] = n;
- excess[source] = INF;
- for (int v = 0; v < n; v++) push(source, v);
-
- int p = 0;
- while (p < n - 2) {
- int v = list[p], oldHeight = height[v];
- discharge(v);
- if (height[v] > oldHeight) {
- moveToFront(p);
- p = 0;
- } else p++;
+ 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;
}
-
- ll maxflow = 0;
- for (int v = 0; v < n; v++) maxflow += flow[source][v];
- return maxflow;
+ int v = llist[highestActive].back();
+ llist[highestActive].pop_back();
+ discharge(n, v);
}
-};
+ return excess[t] + inf;
+}
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]++;
+}}}}}
diff --git a/graph/pushRelabel3.cpp b/graph/pushRelabel3.cpp
deleted file mode 100644
index 4f383f6..0000000
--- a/graph/pushRelabel3.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-struct edge {
- int from, to;
- ll f, c;
-};
-
-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));
- edges.push_back({from, to, 0, c});
- adj[to].push_back(sz(edges));
- edges.push_back({to, from, 0, 0});
-}
-
-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;
-}
-
-ll maxFlow(int s, int t) {
- int n = sz(adj);
- 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]++;
-}}}}}