diff options
| author | Noobie99 <noob999noob999@gmail.com> | 2023-08-29 10:09:15 +0200 |
|---|---|---|
| committer | Noobie99 <noob999noob999@gmail.com> | 2023-08-29 10:09:15 +0200 |
| commit | 911a19c17730d912f5e64e2b8bcc28980a956b8e (patch) | |
| tree | 64992136de00e875043733e9c94fe3efc84336bc /graph | |
| parent | 10df00ff808c6681c31ff115e53fcaafa17d96d1 (diff) | |
remove 1 pushrelabel + consistency
Diffstat (limited to 'graph')
| -rw-r--r-- | graph/pushRelabel.cpp | 158 | ||||
| -rw-r--r-- | graph/pushRelabel2.cpp | 143 | ||||
| -rw-r--r-- | graph/pushRelabel3.cpp | 66 |
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]++; -}}}}} |
