This can be formalized by defining: a is an articulation point of graph G if and only if there exists vertices v,w such that v, w, a are distinct and every path from v to w contains a.
G is biconnected if and only if there are no articulation points. That is, it requires deletion of at least 2 vertices to disconnect G.
A maximal subgraph of G that is biconnected is called a biconnected component of G.
Note that all the edges in a cycle will be in the same biconnected component. We can define an equivalence relation on the edges e1 is equivalent to e2 if either e1 = e2 or there exists a cycle including both e1 and e2. This equivalence relation partitions the set of edges into equivalence classes, where two edges belong to the same equivalence class if and only if they are equivalent.
If E is an equivalence class (of edges) and V is the set of vertices appearing as endpoints of the edges in E then it will be the case that the graph (V,E) is a biconnected component of G.
Lemma. For any connected graph G:
We will use DFS to find the biconnected components of a graph. A DFS tree has no cross-edges. That is, if v is neither an ancestor nor a descendent of w then there is no edge (v,w).
If a is an articulation point of graph G then removing a will split G into two or more parts. One of these parts will consist of a son of a, s, together with all of s's descendents in the DFS tree. This is summarized in the next lemma.
Lemma. a is an articulation point of G
if and only if either
1. a is the root and has more than one son, or
2. a is not the root, and there exists a son s of a
such that there is no backedge between any descendent of s
(including s) and a proper ancestor of a.
Define LOW(v) to be the most remote ancestor of v that can be reached from v if we are allowed to go down the tree from v and then go up at most one backedge.
By the lemma, if the vertices are numbered by DFS numbers then:
if a is not the root then a is an articulation point
if and only if a has a son s such that
LOW(s) ≥ DFN[a].
We will embed in the DFS algorithm the calculation of LOW, using the following recurrence.
LOW(v) = minimum x such that
| either | 1. x = DFN[v] | (no backedge taken) |
| or | 2. x = LOW(s), where s is a son of v | (backedge from a proper descendent of v) |
| or | 3. x = DFN[w], where (v,w) is a backedge | (backedge from v) |
Find articulation points and biconnected components
T := Ø
COUNT := 0
STACK := Λ
forall vertices v do FLAG[v] := "new"
SEARCHB(1)
SEARCHB(v)
FLAG[v] := "old"
COUNT := COUNT + 1
DFN[v] := COUNT
1: LOW[v] := DFN[v]
Let L[v] be the list of vertices adjacent to v
while L[v] ≠ Λ do
w := pop( L[v] )
if (v,w) is not yet on the stack
/** (v,w) is already on the stack if and only if **/
/** (v,w) was a backedge w to v, for w descendent of v. **/
/** This can be expressed by: FATHER[v] = w or **/
/** (FLAG[w]="old" and DFN[v] < DFN[w]) **/
then put (v,w) on STACK
if FLAG[w] = "new" then
T := T union {(v,w)}
FATHER[w] := v
SEARCHB(w)
if LOW[w] ≥ DFN[v] then
v is an articulation point
and the next biconnected component is
the set of edges popped from STACK up to and including (v,w)
2: LOW[v] := min{ LOW[v], LOW[w] }
else if w ≠ FATHER[v] then
3: LOW[v] := min{ LOW[v], DFN[w] }
The time complexity is O(n + e) because the changes from simple DFS are LOW computation and STACK manipulations, each of which takes time O(e).
One can prove by induction on the number of biconnected components of G that, when SEARCHB(w) is completed, if LOW[w] ≥ DFN[v] then the set of edges above (v,w) on the stack constitutes the biconnected component containing edge (v,w).