|
7 | 7 | //! for each edge u -> v: scc_id[u] >= scc_id[v] |
8 | 8 | //! @time O(n + m) |
9 | 9 | //! @space O(n) |
10 | | -pair<int, vector<int>> sccs(const vector<vector<int>>& adj) { |
11 | | - int num_sccs = 0, n = ssize(adj), timer = 0; |
12 | | - vector<int> scc_id(n, -1), tin(n), low(n), st, e(n), p(n, -1); |
13 | | - for (int i = 0; i < n; i++) |
14 | | - if (!tin[i]) { |
15 | | - int v = i; |
16 | | - while (v >= 0) { |
17 | | - if (e[v]) { |
18 | | - int u = adj[v][e[v] - 1]; |
19 | | - if (scc_id[u] == -1) low[v] = min(low[v], low[u]); |
20 | | - } else { |
21 | | - low[v] = tin[v] = ++timer; |
22 | | - st.push_back(v); |
23 | | - } |
24 | | - if (e[v] < ssize(adj[v])) { |
25 | | - int u = adj[v][e[v]++]; |
26 | | - if (!tin[u]) p[u] = v, v = u; |
27 | | - } else { |
28 | | - if (low[v] == tin[v]) { |
29 | | - while (scc_id[v] == -1) { |
30 | | - scc_id[st.back()] = num_sccs; |
31 | | - st.pop_back(); |
32 | | - } |
33 | | - num_sccs++; |
34 | | - } |
35 | | - v = p[v]; |
36 | | - } |
| 10 | +struct sccs { |
| 11 | + int num_sccs = 0; |
| 12 | + vi scc_id; |
| 13 | + sccs(const vector<vi>& adj): scc_id(sz(adj), -1) { |
| 14 | + int n = sz(adj), timer = 1; |
| 15 | + vi tin(n), st; |
| 16 | + auto dfs = [&](auto&& self, int v) -> int { |
| 17 | + int low = tin[v] = timer++, siz = sz(st); |
| 18 | + st.push_back(v); |
| 19 | + for (int u : adj[v]) |
| 20 | + if (scc_id[u] < 0) |
| 21 | + low = min(low, tin[u] ? tin[u] : self(self, u)); |
| 22 | + if (tin[v] == low) { |
| 23 | + rep(i, siz, sz(st)) scc_id[st[i]] = num_sccs; |
| 24 | + st.resize(siz); |
| 25 | + num_sccs++; |
37 | 26 | } |
38 | | - } |
39 | | - return {num_sccs, scc_id}; |
40 | | -} |
| 27 | + return low; |
| 28 | + }; |
| 29 | + rep(i, 0, n) if (!tin[i]) dfs(dfs, i); |
| 30 | + } |
| 31 | +}; |
0 commit comments