55// Let G = (V, E). If G-v is disconnected, v in V is said to
66// be an articulation point. If G has no articulation points,
77// it is said to be biconnected.
8+ //
89// A biconnected component is a maximal biconnected subgraph.
910// The algorithm finds all articulation points and biconnected
1011// components.
1112//
13+ // The most important fact is that by contracting biconnected
14+ // components we obtain a tree, which is called the block tree.
15+ //
16+ //
1217// Algorithm:
1318// Hopcroft-Tarjan's DFS based algorithm.
1419//
20+ // Single DFS finds a block tree rooted from the component
21+ // that contains the specified root.
22+ //
1523// Complexity:
1624// O(n + m).
1725//
@@ -46,36 +54,39 @@ struct graph {
4654 adj[src].push_back (dst);
4755 adj[dst].push_back (src);
4856 }
49- };
5057
51- void biconnected_components (graph g) {
52- vector<int > arts (g.n ), num (g.n ), low (g.n ), S;
53- vector<vector<int >> comps;
54- function<void (int ,int ,int &)> dfs = [&](int p, int i, int &t) {
55- num[i] = low[i] = ++t;
56- S.push_back (i);
57- for (int j: g.adj [i]) {
58- if (j == p) continue ;
59- if (num[j] == 0 ) {
60- dfs (i, j, t);
61- low[i] = min (low[i], low[j]);
62- if (num[i] <= low[j]) {
63- if (num[i] != 1 || low[j] > 2 ) arts[i] = true ;
64- for (comps.push_back ({i}); comps.back ().back () != j; S.pop_back ())
65- comps.back ().push_back (S.back ()); //
66- }
67- } else low[i] = min (low[i], num[j]);
68- }
69- };
70- for (int i = 0 , t; i < g.n ; ++i)
71- if (num[i] == 0 ) dfs (-1 , i, t = 0 );
58+ void biconnected_components () {
59+ vector<int > num (n), low (n), S;
60+ unordered_set<int > arts;
7261
73- // SPOJ SUBMERGE
74- int count = 0 ;
75- for (int i = 0 ; i < g.n ; ++i)
76- count += arts[i];
77- printf (" %d\n " , count);
78- }
62+ function<void (int ,int ,int &)> dfs = [&](int p, int u, int &t) {
63+ num[u] = low[u] = ++t;
64+ S.push_back (u);
65+ for (int v: adj[u]) {
66+ if (v == p) continue ;
67+ if (num[v] == 0 ) {
68+ dfs (u, v, t);
69+ low[u] = min (low[u], low[v]);
70+ if (num[u] <= low[v]) {
71+ if (num[u] != 1 || num[v] > 2 ) {
72+ // here, u is an articulation point if
73+ // (a). u is non-root
74+ // (b). u is root with two more children
75+ }
76+ vector<int > C = {u}; // biconnected component
77+ while (C.back () != v) {
78+ C.push_back (S.back ());
79+ S.pop_back ();
80+ }
81+ }
82+ } else low[u] = min (low[u], num[v]);
83+ }
84+ };
85+ for (int u = 0 , t; u < n; ++u)
86+ if (!num[u]) dfs (-1 , u, t = 0 );
87+ cout << arts.size () << endl;
88+ }
89+ };
7990
8091int main () {
8192 for (int n, m; ~scanf (" %d %d" , &n, &m) && n; ) {
@@ -84,6 +95,6 @@ int main() {
8495 int u, v; scanf (" %d %d" , &u, &v);
8596 g.add_edge (u-1 , v-1 );
8697 }
87- biconnected_components (g );
98+ g. biconnected_components ();
8899 }
89100}
0 commit comments