Skip to content

Commit 20bfef2

Browse files
author
Takanori MAEHARA
authored
Biconnected components and Articulation points (Hopcroft-Tarjan)
1 parent 088c447 commit 20bfef2

1 file changed

Lines changed: 40 additions & 29 deletions

File tree

graph/articulation_points.cc

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,21 @@
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

8091
int 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

Comments
 (0)