1+ #ifndef CP_ALGO_GRAPH_BCC_HPP
2+ #define CP_ALGO_GRAPH_BCC_HPP
3+ #include " base.hpp"
4+ #include " ../structures/csr.hpp"
5+ #include < algorithm>
6+
7+ namespace cp_algo ::graph {
8+ template <undirected_graph_type graph>
9+ structures::csr<node_index> biconnected_components (graph const & g) {
10+ structures::csr<node_index> components;
11+ components.reserve_data (g.n ());
12+ enum node_state { unvisited, visited, blocked };
13+ std::vector<node_state> state (g.n ());
14+
15+ auto collect = [&](this auto &&collect, node_index v) -> void {
16+ state[v] = blocked;
17+ components.push (v);
18+ for (auto e : g.outgoing (v)) {
19+ node_index u = g.edge (e).to ;
20+ if (state[u] != blocked) collect (u);
21+ }
22+ };
23+
24+ big_vector<int > tin (g.n ()), low (g.n ());
25+ int timer = 0 ;
26+ auto dfs = [&](this auto &&dfs, node_index v, edge_index ep = -1 ) -> void {
27+ tin[v] = low[v] = timer++;
28+ state[v] = blocked;
29+ for (auto e: g.outgoing (v)) {
30+ if (ep == graph::opposite_idx (e)) {
31+ continue ;
32+ }
33+ node_index u = g.edge (e).to ;
34+ if (state[u] == unvisited) {
35+ dfs (u, e);
36+ if (low[u] >= tin[v] && state[u] != blocked) {
37+ components.new_row ();
38+ collect (u);
39+ components.push (v);
40+ }
41+ low[v] = std::min (low[v], low[u]);
42+ } else {
43+ low[v] = std::min (low[v], tin[u]);
44+ }
45+ }
46+ state[v] = visited;
47+ };
48+
49+ for (auto v : g.nodes ()) {
50+ if (state[v] == unvisited) {
51+ if (std::ranges::empty (g.outgoing (v))) {
52+ components.new_row ();
53+ components.push (v);
54+ } else {
55+ dfs (v);
56+ }
57+ }
58+ }
59+ return components;
60+ }
61+ }
62+
63+ #endif // CP_ALGO_GRAPH_BCC_HPP
0 commit comments