Skip to content

Commit fe11f63

Browse files
committed
feat: Add TwoEdgeConnectedComponents implementation and test case
1 parent bef4fc1 commit fe11f63

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-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/two_edge_connected_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+
TwoEdgeConnectedComponents 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.eccs.size() << '\n';
24+
for (const auto &ecc : graph.eccs) {
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: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#ifndef WEILYCODER_TARJAN_HPP
2+
#define WEILYCODER_TARJAN_HPP
3+
4+
#include <cstddef>
5+
#include <stack>
6+
#include <utility>
7+
#include <vector>
8+
9+
namespace weilycoder {
10+
template <typename ptr_t = size_t> struct TwoEdgeConnectedComponents {
11+
ptr_t dfs_time = 0, edge_time = 1;
12+
13+
std::vector<bool> in_stack;
14+
std::stack<ptr_t> stk;
15+
std::vector<ptr_t> dfn, low;
16+
std::vector<std::vector<std::pair<ptr_t, ptr_t>>> graph;
17+
18+
std::vector<std::vector<ptr_t>> eccs;
19+
20+
TwoEdgeConnectedComponents(ptr_t n)
21+
: in_stack(n, false), dfn(n, 0), low(n, 0), graph(n) {}
22+
23+
void add_edge(ptr_t u, ptr_t v) {
24+
graph[u].emplace_back(v, edge_time);
25+
graph[v].emplace_back(u, edge_time);
26+
edge_time++;
27+
}
28+
29+
void tarjan(ptr_t u, ptr_t parent_edge) {
30+
dfn[u] = low[u] = ++dfs_time;
31+
stk.push(u);
32+
in_stack[u] = true;
33+
34+
for (const auto &[v, edge_id] : graph[u]) {
35+
if (edge_id == parent_edge)
36+
continue;
37+
if (!dfn[v])
38+
tarjan(v, edge_id), low[u] = std::min(low[u], low[v]);
39+
else if (in_stack[v])
40+
low[u] = std::min(low[u], dfn[v]);
41+
}
42+
43+
if (dfn[u] == low[u]) {
44+
eccs.emplace_back();
45+
eccs.back().push_back(u);
46+
in_stack[u] = false;
47+
while (stk.top() != u)
48+
eccs.back().push_back(stk.top()), in_stack[stk.top()] = false, stk.pop();
49+
stk.pop();
50+
}
51+
}
52+
53+
void solve() {
54+
for (size_t i = 0; i < graph.size(); ++i)
55+
if (!dfn[i])
56+
tarjan(i, 0);
57+
}
58+
};
59+
} // namespace weilycoder
60+
61+
#endif

0 commit comments

Comments
 (0)