Skip to content

Commit 1da2c6c

Browse files
committed
feat: Add BiconnectedComponents implementation and corresponding test case
1 parent 7813902 commit 1da2c6c

File tree

2 files changed

+84
-4
lines changed

2 files changed

+84
-4
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/biconnected_components"
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+
BiconnectedComponents 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.dccs.size() << '\n';
24+
for (const auto &dcc : graph.dccs) {
25+
cout << dcc.size();
26+
for (size_t u : dcc)
27+
cout << ' ' << u;
28+
cout << '\n';
29+
}
30+
return 0;
31+
}

weilycoder/graph/tarjan.hpp

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ template <typename ptr_t = size_t> struct TwoEdgeConnectedComponents {
2929

3030
void tarjan(ptr_t u, ptr_t parent_edge) {
3131
dfn[u] = low[u] = ++dfs_time;
32-
stk.push(u);
33-
in_stack[u] = true;
32+
stk.push(u), in_stack[u] = true;
3433

3534
for (const auto &[v, edge_id] : graph[u]) {
3635
if (edge_id == parent_edge)
@@ -75,8 +74,7 @@ template <typename ptr_t = size_t> struct StrongConnectedComponents {
7574

7675
void tarjan(ptr_t u) {
7776
dfn[u] = low[u] = ++dfs_time;
78-
stk.push(u);
79-
in_stack[u] = true;
77+
stk.push(u), in_stack[u] = true;
8078

8179
for (const auto &v : graph[u]) {
8280
if (!dfn[v])
@@ -102,6 +100,57 @@ template <typename ptr_t = size_t> struct StrongConnectedComponents {
102100
std::reverse(sccs.begin(), sccs.end());
103101
}
104102
};
103+
104+
template <typename ptr_t = size_t> struct BiconnectedComponents {
105+
ptr_t dfs_time = 0;
106+
107+
std::stack<ptr_t> stk;
108+
std::vector<ptr_t> dfn, low;
109+
std::vector<std::vector<ptr_t>> graph;
110+
111+
std::vector<bool> is_cut;
112+
std::vector<std::vector<ptr_t>> dccs;
113+
114+
BiconnectedComponents(ptr_t n) : dfn(n, 0), low(n, 0), graph(n), is_cut(n, false) {}
115+
116+
void add_edge(ptr_t u, ptr_t v) {
117+
graph[u].push_back(v);
118+
graph[v].push_back(u);
119+
}
120+
121+
void tarjan(ptr_t u, bool is_root) {
122+
dfn[u] = low[u] = ++dfs_time, stk.push(u);
123+
124+
if (is_root && graph[u].empty()) {
125+
dccs.emplace_back();
126+
dccs.back().push_back(u);
127+
return;
128+
}
129+
130+
ptr_t child = 0;
131+
for (const auto &v : graph[u]) {
132+
if (!dfn[v]) {
133+
tarjan(v, false), low[u] = std::min(low[u], low[v]);
134+
if (low[v] >= dfn[u]) {
135+
if (++child > 1 || !is_root)
136+
is_cut[u] = true;
137+
dccs.emplace_back();
138+
do
139+
dccs.back().push_back(stk.top()), stk.pop();
140+
while (dccs.back().back() != v);
141+
dccs.back().push_back(u);
142+
}
143+
} else
144+
low[u] = std::min(low[u], dfn[v]);
145+
}
146+
}
147+
148+
void solve() {
149+
for (size_t i = 0; i < graph.size(); ++i)
150+
if (!dfn[i])
151+
tarjan(i, true);
152+
}
153+
};
105154
} // namespace weilycoder
106155

107156
#endif

0 commit comments

Comments
 (0)