|
| 1 | +#pragma once |
| 2 | +//! https://cp-algorithms.com/graph/cutpoints.html |
| 3 | +//! @code |
| 4 | +//! { |
| 5 | +//! vector<vector<pii>> adj(n); |
| 6 | +//! auto [num_bccs, bcc_id, is_cut] = cuts(adj, m); |
| 7 | +//! } |
| 8 | +//! vector<basic_string<array<int, 2>>> adj(n); |
| 9 | +//! rep (i, 0, m) { |
| 10 | +//! int u, v; |
| 11 | +//! cin >> u >> v; |
| 12 | +//! u--, v--; |
| 13 | +//! //self edges not allowed |
| 14 | +//! adj[u] += {v, i}; |
| 15 | +//! adj[v] += {u, i}; |
| 16 | +//! } |
| 17 | +//! auto [num_bccs, bcc_id, is_cut] = cuts(adj, m); |
| 18 | +//! @endcode |
| 19 | +//! @time O(n + m) |
| 20 | +//! @space O(n + m) |
| 21 | +/* |
| 22 | +auto cuts(const auto& adj, int m) { |
| 23 | + int n = sz(adj), num_bccs = 0, q = 0, s = 0; |
| 24 | + vi bcc_id(m, -1), is_cut(n), tin(n), st(m); |
| 25 | + auto dfs = [&](auto&& self, int v, int p) -> int { |
| 26 | + int low = tin[v] = ++q; |
| 27 | + for (auto [u, e] : adj[v]) { |
| 28 | + assert(v != u); |
| 29 | + if (e == p) continue; |
| 30 | + if (tin[u] < tin[v]) st[s++] = e; |
| 31 | + int lu = -1; |
| 32 | + low = min(low, tin[u] ?: (lu = self(self, u, e))); |
| 33 | + if (lu >= tin[v]) { |
| 34 | + is_cut[v] = p >= 0 || tin[v] + 1 < tin[u]; |
| 35 | + while (bcc_id[e] < 0) bcc_id[st[--s]] = num_bccs; |
| 36 | + num_bccs++; |
| 37 | + } |
| 38 | + } |
| 39 | + return low; |
| 40 | + }; |
| 41 | + rep(i, 0, n) if (!tin[i]) dfs(dfs, i, -1); |
| 42 | + return tuple{num_bccs, bcc_id, is_cut}; |
| 43 | +} |
| 44 | +*/ |
| 45 | +void cuts_callback(const auto& adj, auto f) { |
| 46 | + int n = ssize(adj), q = 0, s = 0; |
| 47 | + vector<int> tin(n), st(n); |
| 48 | + auto dfs = [&](auto&& self, int v, int p) -> int { |
| 49 | + int low = tin[v] = ++q; |
| 50 | + for (int u : adj[v]) if (u != p) { |
| 51 | + int siz = s, lu = 0; |
| 52 | + low = min(low, tin[u] ?: (lu = self(self, st[s++] = u, v))); |
| 53 | + if (lu >= tin[v]) { |
| 54 | + f(v, vector<int>(begin(st) + siz, begin(st) + s)); |
| 55 | + s = siz; |
| 56 | + } |
| 57 | + } |
| 58 | + return low; |
| 59 | + }; |
| 60 | + for (int i = 0; i <n; i++) if (!tin[i]) dfs(dfs, i, i); |
| 61 | +} |
0 commit comments