From e6e5ec000d26f97c23eacf1e3852a61d74032016 Mon Sep 17 00:00:00 2001 From: Luke Videckis Date: Mon, 16 Mar 2026 13:36:58 -0600 Subject: [PATCH] u - current node, v - child --- library/flow/dinic.hpp | 61 ------------------- library/trees/centroid_decomp.hpp | 32 +++++----- library/trees/edge_cd.hpp | 40 ++++++------ .../dinic_asserts.hpp | 42 ------------- .../flow/dinic_aizu.test.cpp | 20 ------ 5 files changed, 36 insertions(+), 159 deletions(-) delete mode 100644 library/flow/dinic.hpp delete mode 100644 tests/library_checker_aizu_tests/dinic_asserts.hpp delete mode 100644 tests/library_checker_aizu_tests/flow/dinic_aizu.test.cpp diff --git a/library/flow/dinic.hpp b/library/flow/dinic.hpp deleted file mode 100644 index 7d09a6875..000000000 --- a/library/flow/dinic.hpp +++ /dev/null @@ -1,61 +0,0 @@ -//! https://github.com/kth-competitive-programming/kactl/blob/main/content/graph/Dinic.h -//! @code -//! const int src = n, snk = n + 1; -//! dinic dn(n + 2); -//! int e_id = dn.add_edge(u, v, cap); -//! ll tot_flow = dn.calc(src, snk); -//! dinic::edge an_edge = dn.edges[e_id]; -//! @endcode -//! @time O(n * m * log(max_cap)) -//! O(min(sqrt(m), n^(2/3)) * m) if max_cap==1 -//! O(m * sqrt(n)) for bipartite matching -//! @space O(n + m) -struct dinic { - struct edge { - int v, to; - ll c, cap; - ll flow() { return cap - c; } - }; - ll max_cap = 1; - vi lvl, ptr, q; - vector adj; - vector edges; - dinic(int n): lvl(n), ptr(n), q(n), adj(n) {} - int add_edge(int a, int b, ll c) { - adj[a].push_back(sz(edges)); - edges.push_back({a, b, c, c}); - adj[b].push_back(sz(edges)); - edges.push_back({-1, a, 0, -1}); - max_cap = max(max_cap, c); - return sz(edges) - 2; - } - ll dfs(int v, int t, ll f) { - if (v == t || !f) return f; - for (int& i = ptr[v]; i < sz(adj[v]); i++) { - edge& e = edges[adj[v][i]]; - if (lvl[e.to] == lvl[v] + 1) - if (ll p = dfs(e.to, t, min(f, e.c))) { - e.c -= p, edges[adj[v][i] ^ 1].c += p; - return p; - } - } - return 0; - } - ll calc(int s, int t) { - ll flow = 0; - q[0] = s; - for (ll i = max_cap; i; i /= 2) do { - lvl = ptr = vi(sz(q)); - int qi = 0, qe = lvl[s] = 1; - while (qi < qe && !lvl[t]) { - int v = q[qi++]; - for (int id : adj[v]) - if (edge e = edges[id]; !lvl[e.to] && e.c >= i) - q[qe++] = e.to, lvl[e.to] = lvl[v] + 1; - } - while (ll p = dfs(s, t, LLONG_MAX)) flow += p; - } while (lvl[t]); - return flow; - } - bool left_of_min_cut(int v) { return lvl[v]; } -}; diff --git a/library/trees/centroid_decomp.hpp b/library/trees/centroid_decomp.hpp index 3cd5d12d8..950f8a6ba 100644 --- a/library/trees/centroid_decomp.hpp +++ b/library/trees/centroid_decomp.hpp @@ -14,25 +14,25 @@ template struct centroid { adj(adj), f(f), siz(sz(adj), -1) { dfs(0, -1); } - void calc_sz(int v, int p) { - siz[v] = 1; - for (int u : adj[v]) - if (u != p) calc_sz(u, v), siz[v] += siz[u]; + void calc_sz(int u, int p) { + siz[u] = 1; + for (int v : adj[u]) + if (v != p) calc_sz(v, u), siz[u] += siz[v]; } - void dfs(int v, int p) { - calc_sz(v, -1); - for (int w = -1, sz_root = siz[v];;) { - auto big_ch = ranges::find_if(adj[v], [&](int u) { - return u != w && 2 * siz[u] > sz_root; + void dfs(int u, int p) { + calc_sz(u, -1); + for (int w = -1, sz_root = siz[u];;) { + auto big_ch = ranges::find_if(adj[u], [&](int v) { + return v != w && 2 * siz[v] > sz_root; }); - if (big_ch == end(adj[v])) break; - w = v, v = *big_ch; + if (big_ch == end(adj[u])) break; + w = u, u = *big_ch; } - f(adj, v, p); - for (int u : adj[v]) { - iter_swap(ranges::find(adj[u], v), rbegin(adj[u])); - adj[u].pop_back(); - dfs(u, v); + f(adj, u, p); + for (int v : adj[u]) { + iter_swap(ranges::find(adj[v], u), rbegin(adj[v])); + adj[v].pop_back(); + dfs(v, u); } } }; diff --git a/library/trees/edge_cd.hpp b/library/trees/edge_cd.hpp index e3ec20cd7..f90e38ae8 100644 --- a/library/trees/edge_cd.hpp +++ b/library/trees/edge_cd.hpp @@ -21,31 +21,31 @@ template struct edge_cd { adj(adj), f(f), siz(sz(adj)) { dfs(0, sz(adj) - 1); } - int find_cent(int v, int p, int m) { - siz[v] = 1; - for (int u : adj[v]) - if (u != p) { - int cent = find_cent(u, v, m); + int find_cent(int u, int p, int m) { + siz[u] = 1; + for (int v : adj[u]) + if (v != p) { + int cent = find_cent(v, u, m); if (cent != -1) return cent; - siz[v] += siz[u]; + siz[u] += siz[v]; } - return 2 * siz[v] > m - ? p >= 0 && (siz[p] = m + 1 - siz[v]), - v : -1; + return 2 * siz[u] > m + ? p >= 0 && (siz[p] = m + 1 - siz[u]), + u : -1; } - void dfs(int v, int m) { + void dfs(int u, int m) { if (m < 2) return; - v = find_cent(v, -1, m); + u = find_cent(u, -1, m); int sum = 0; - auto it = partition(all(adj[v]), [&](int u) { - ll x = sum + siz[u]; - return x * x < m * (m - x) ? sum += siz[u], 1 : 0; + auto it = partition(all(adj[u]), [&](int v) { + ll x = sum + siz[v]; + return x * x < m * (m - x) ? sum += siz[v], 1 : 0; }); - f(adj, v, it - begin(adj[v])); - G oth(it, end(adj[v])); - adj[v].erase(it, end(adj[v])); - dfs(v, sum); - swap(adj[v], oth); - dfs(v, m - sum); + f(adj, u, it - begin(adj[u])); + G oth(it, end(adj[u])); + adj[u].erase(it, end(adj[u])); + dfs(u, sum); + swap(adj[u], oth); + dfs(u, m - sum); } }; diff --git a/tests/library_checker_aizu_tests/dinic_asserts.hpp b/tests/library_checker_aizu_tests/dinic_asserts.hpp deleted file mode 100644 index f00c21852..000000000 --- a/tests/library_checker_aizu_tests/dinic_asserts.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -void dinic_asserts(dinic& d, int source, int sink, - ll total_flow) { - int n = sz(d.q); - vector in_flow(n), out_flow(n); - for (int i = 0; i < sz(d.edges); i += 2) { - dinic::edge e = d.edges[i]; - out_flow[e.v] += e.flow(); - in_flow[e.to] += e.flow(); - assert(0 <= e.flow() && e.flow() <= e.cap); - } - assert(in_flow[source] == 0); - assert(out_flow[source] == total_flow); - assert(in_flow[sink] == total_flow); - assert(out_flow[sink] == 0); - for (int i = 0; i < n; i++) { - if (i == source) continue; - if (i == sink) continue; - assert(in_flow[i] == out_flow[i]); - } - { - queue q; - q.push(source); - vector vis(n); - vis[source] = 1; - while (!empty(q)) { - int v = q.front(); - q.pop(); - for (int id : d.adj[v]) { - dinic::edge e = d.edges[id]; - if (e.flow() == e.cap) continue; - int u = e.to; - if (!vis[u]) { - vis[u] = 1; - q.push(u); - } - } - } - for (int i = 0; i < n; i++) - assert(vis[i] == d.left_of_min_cut(i)); - } -} diff --git a/tests/library_checker_aizu_tests/flow/dinic_aizu.test.cpp b/tests/library_checker_aizu_tests/flow/dinic_aizu.test.cpp deleted file mode 100644 index 60fc043f8..000000000 --- a/tests/library_checker_aizu_tests/flow/dinic_aizu.test.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/library/5/GRL/all/GRL_6_A" -#include "../template.hpp" -#include "../../../library/flow/dinic.hpp" -#include "../dinic_asserts.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - dinic d(n); - for (int i = 0; i < m; i++) { - int u, v, cap; - cin >> u >> v >> cap; - d.add_edge(u, v, cap); - } - ll total_flow = d.calc(0, n - 1); - dinic_asserts(d, 0, n - 1, total_flow); - cout << total_flow << '\n'; - return 0; -}