Skip to content

Commit b9b6012

Browse files
committed
feat: Implement StrongConnectedComponents class and add test case
1 parent c6b3840 commit b9b6012

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#define PROBLEM "https://judge.yosupo.jp/problem/scc"
2+
3+
#include "../weilycoder/graph/tarjan.hpp"
4+
#include <iostream>
5+
using namespace std;
6+
using namespace weilycoder;
7+
8+
int main() {
9+
cin.tie(nullptr)->sync_with_stdio(false);
10+
cin.exceptions(cin.failbit | cin.badbit);
11+
size_t n, m;
12+
cin >> n >> m;
13+
14+
StrongConnectedComponents graph(n);
15+
for (size_t i = 0; i < m; ++i) {
16+
size_t u, v;
17+
cin >> u >> v;
18+
graph.add_edge(u, v);
19+
}
20+
21+
graph.solve();
22+
23+
cout << graph.sccs.size() << '\n';
24+
for (const auto &ecc : graph.sccs) {
25+
cout << ecc.size();
26+
for (size_t u : ecc)
27+
cout << ' ' << u;
28+
cout << '\n';
29+
}
30+
return 0;
31+
}

weilycoder/graph/tarjan.hpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef WEILYCODER_TARJAN_HPP
22
#define WEILYCODER_TARJAN_HPP
33

4+
#include <algorithm>
45
#include <cstddef>
56
#include <stack>
67
#include <utility>
@@ -56,6 +57,51 @@ template <typename ptr_t = size_t> struct TwoEdgeConnectedComponents {
5657
tarjan(i, 0);
5758
}
5859
};
60+
61+
template <typename ptr_t = size_t> struct StrongConnectedComponents {
62+
ptr_t dfs_time = 0;
63+
64+
std::vector<bool> in_stack;
65+
std::stack<ptr_t> stk;
66+
std::vector<ptr_t> dfn, low;
67+
std::vector<std::vector<ptr_t>> graph;
68+
69+
std::vector<std::vector<ptr_t>> sccs;
70+
71+
StrongConnectedComponents(ptr_t n)
72+
: in_stack(n, false), dfn(n, 0), low(n, 0), graph(n) {}
73+
74+
void add_edge(ptr_t u, ptr_t v) { graph[u].push_back(v); }
75+
76+
void tarjan(ptr_t u) {
77+
dfn[u] = low[u] = ++dfs_time;
78+
stk.push(u);
79+
in_stack[u] = true;
80+
81+
for (const auto &v : graph[u]) {
82+
if (!dfn[v])
83+
tarjan(v), low[u] = std::min(low[u], low[v]);
84+
else if (in_stack[v])
85+
low[u] = std::min(low[u], dfn[v]);
86+
}
87+
88+
if (dfn[u] == low[u]) {
89+
sccs.emplace_back();
90+
sccs.back().push_back(u);
91+
in_stack[u] = false;
92+
while (stk.top() != u)
93+
sccs.back().push_back(stk.top()), in_stack[stk.top()] = false, stk.pop();
94+
stk.pop();
95+
}
96+
}
97+
98+
void solve() {
99+
for (size_t i = 0; i < graph.size(); ++i)
100+
if (!dfn[i])
101+
tarjan(i);
102+
std::reverse(sccs.begin(), sccs.end());
103+
}
104+
};
59105
} // namespace weilycoder
60106

61107
#endif

0 commit comments

Comments
 (0)