Bridges & Articulation Points
A bridge is an edge whose removal disconnects the graph; an articulation point is a vertex whose removal does. Both are single points of failure in a network.
╌╌╌╌
We have seen depth-first search lay a tree over a graph, and we used that tree to direct edges, find cycles, and decompose a digraph into strongly connected components. This lesson turns the same machinery on a different question, one that matters whenever a graph models a network: which parts of it are fragile? If a single fiber link is cut or a single router fails, the network may split into pieces that can no longer reach one another. These single points of failure have names.
A graph with no bridges is 2-edge-connected: you must cut at least two edges
to disconnect it, so every pair of vertices is joined by two edge-disjoint paths.
A graph with no articulation points (and at least three vertices) is
2-vertex-connected, or biconnected: two vertex-disjoint paths between every
pair.1 The maximal biconnected subgraphs are the biconnected
components; bridges and cut vertices are the seams where they meet. So
the question where is my network fragile?
is the question find the cut edges and cut vertices,
and one DFS answers it.
The DFS-tree view
Run DFS from any vertex of a connected, undirected graph. Classify each edge by when DFS first traverses it. The decisive structural fact is that only two kinds survive.
This is what makes undirected connectivity tractable: the only way to leave a DFS subtree is a back edge climbing to an ancestor. Bridges and cut vertices are both about whether such an escape exists. To detect it we time the search and track how high each subtree can climb.
In words, is the smallest discovery time reachable from 's DFS subtree using any number of tree edges (downward) plus at most one back edge (the final hop up). It measures the highest ancestor the subtree rooted at can reach without going through 's parent. Both quantities are computed in the same recursion: set on entry, then relax against each child's finished and each back edge's target .
In the figure each node is labeled . The back edge pulls , so the subtrees of and can all climb back above their parents: none of , is a bridge. But is a dead end, , nothing in 's subtree reaches above , so cutting strands . The edge is a bridge too, since 's only escape, the back edge , stays inside 's own subtree.
The bridge criterion
The criterion is a decision test on a single edge — is this a bridge? — and the iff is its two-sided correctness in the sense of the foundations. The forward direction ( implies the edge really is a bridge) is its soundness: the test never flags a safe edge. The reverse (a true bridge always satisfies , since otherwise a back edge offers an alternative route) is its completeness: no bridge is missed.
The articulation criterion
Cut vertices need one more case, because removing deletes all of 's incident edges at once, including the tree edges to each child.
Here the back edge gives . The subtree of can climb to but no higher, so holds and is a cut vertex: deleting it strands and from . Yet the edge is not a bridge, since is not strictly greater. The same local data, two thresholds apart, distinguishes fragile edges from fragile vertices.
One DFS finds them all
Both criteria read off and , so a single recursion computes everything. The one subtlety is the parent edge: in an undirected graph the edge back to the parent must not be mistaken for a back edge that lowers . Guarding by parent vertex is correct only when there are no multi-edges (two distinct edges between the same pair); with multi-edges, a second –parent edge is a genuine back edge and the second copy must be allowed to lower . The reliable fix is to track the parent edge id rather than the parent vertex.
- 1;\ \ (0 = unvisited)
- 2for each vertex in do
- 3if thennil = no parent edge
- 4
- 5procedure := id of edge to parent
- 6
- 7
- 8
- 9for each incident edge do
- 10if then continueskip arrival edge
- 11if thentree edge
- 12
- 13
- 14
- 15if then report bridge
- 16if and then mark articulation
- 17elseback edge
- 18
- 19if and then mark articulation
Each vertex is discovered once and each edge is examined a constant number of times (twice over the whole run, once from each endpoint), so the search is , asymptotically free on top of the DFS we were already running. The outer loop over makes it work on disconnected graphs as well: it finds the bridges and cut vertices of every component. The same low-link bookkeeping, with a stack of edges, also peels off the biconnected components directly (pop the stack down to whenever ), which is Tarjan's original formulation.23
A complete trace
Here is the whole computation, step by step, on a seven-vertex graph built from two triangles joined by a chain: triangle , bridge , triangle , bridge . Deleting , , or splits the graph, so those three are its cut vertices.
Start DFS at with alphabetical adjacency lists. The recursion discovers the chain (each vertex's first unvisited neighbor happens to be the next letter), and the interesting work happens on the way back up:
| step | event | effect |
|---|---|---|
| 1 | discover | |
| 2 | discover via tree edge | |
| 3 | discover via tree edge | |
| 4 | sees : back edge | |
| 5 | discover via tree edge | |
| 6 | discover via tree edge | |
| 7 | discover via tree edge | |
| 8 | sees : back edge | |
| 9 | discover via tree edge | ; has no other neighbor, returns |
| 10 | returns to | ; : bridge ; : is a cut vertex |
| 11 | returns to | ; : no bridge, no cut |
| 12 | returns to | ; : is a cut vertex (but : is no bridge) |
| 13 | sees : second view of edge | , no change |
| 14 | returns to | ; : bridge ; : is a cut vertex |
| 15 | returns to | ; : nothing |
| 16 | returns to | ; root has tree child: not a cut vertex |
| 17 | sees : second view of edge | , no change |
Steps 13 and 17 show a quiet feature of undirected DFS: every non-tree edge is examined twice, once from each endpoint. The view from the ancestor side ( looking at , looking at ) relaxes against a larger discovery time and never changes anything; only the view from the descendant side (steps 4 and 8) matters. Both sightings are harmless as long as neither is mistaken for the parent edge.
The final state, drawn on the DFS tree — which for this graph is a single chain — with each vertex labeled :
Reading the picture against the two criteria: the back edge pins at across the first triangle, so nothing in is separated by removing one edge; the back edge pins at across the second. The only tree edges whose child cannot climb past the parent are () and () — the two bridges. And the children , , certify , , as cut vertices via , while the root , with a single tree child, is exempt.
Common pitfalls
- The root always passes the non-root test. Since is the smallest discovery time in its tree, every child satisfies . Apply the non-root rule to the root and it is flagged unconditionally. The root must be special-cased by counting tree children — and tree children, not neighbors: in a triangle the root has degree but only one tree child (the other neighbor is reached around the cycle), and it is correctly not a cut vertex.
- Skipping the parent by vertex instead of by edge. With parallel edges,
ignore neighbors equal to my parent
skips both copies of a doubled edge, so the child looks trapped and the pair is reported as a bridge — but a doubled edge is never a bridge, since the twin copy survives any single cut. Track the id (or adjacency-list index) of the arrival edge and skip only that one; the second copy then acts as a legitimate back edge and lowers . - Relaxing back edges with instead of . The definition permits at most one back edge per escape route, and the proofs lean on it. While is still gray, is a moving target, and chaining through it can credit with escape routes that pass through vertices whose deletion is under test. Back edges relax against , tree edges against the child's finished .
- Testing the wrong pair. The bridge test compares the child's low against the parent's disc: . Both nearby variants fail. Comparing flags every tree edge, since children are always discovered later. Comparing breaks when has its own escape: attach a triangle below a vertex , plus a back edge from to 's parent . Then , so misreports the cycle edge as a bridge even though sit on a common cycle.
- Recursion depth. The DFS tree of a path graph is the whole path; on a million-vertex chain the recursive version overflows most default call stacks. An explicit-stack rewrite must still perform the post-visit relaxation when a child is popped, which takes some care to get right; test it on long chains.
The parallel-edge trap deserves a picture, because the buggy and correct runs differ on the smallest possible graph:
On the left, 's only edges both lead to its parent, both are skipped, and stays at : the doubled edge is declared a bridge, wrongly. On the right, only the arrival copy is skipped; the twin is processed as a back edge (dashed), drops to , and the strict test correctly reports nothing.
When to reach for this
The low-link machinery answers what breaks if one element fails,
and it
shows up wherever that question does: single points of failure in a computer
or transport network, load-bearing joints in a mesh, and the decomposition of
a graph into biconnected components before running algorithms that assume
2-connectivity. Two contrasts are worth keeping straight. First, bridges and
cut vertices concern undirected connectivity; the analogous directed
question is answered by strongly connected
components, and Tarjan's SCC
algorithm reuses this same low-link idea with a stack. Second, the criteria
are about single failures only — surviving the loss of any edges or
vertices is -connectivity, which calls for maximum-flow techniques
rather than one DFS.
Connectivity, statically and dynamically
The block-cut tree. Grouping the graph's biconnected components (blocks) and articulation points into a tree — a node per block, a node per cut vertex, an edge whenever a cut vertex lies on a block — gives the block-cut tree, a compact map of exactly how the graph can fall apart.4 Any two vertices in the same block survive the loss of one vertex; a path between blocks in the tree passes through precisely the cut vertices that would disconnect them. Many is the graph still connected if I delete
queries become tree lookups after one preprocessing pass. The edge analogue, contracting each 2-edge-connected component, yields the bridge tree, in which each tree edge is a bridge of the graph.
Beyond single failures. Bridges and cut vertices are the case of a hierarchy. Surviving any two edge failures is 3-edge-connectivity; the general question is the graph -connected
is answered by max-flow (Menger's theorem equates the minimum – cut with the number of vertex- or edge-disjoint – paths), and global -edge-connectivity by the Stoer-Wagner minimum-cut algorithm. The single-DFS low-link trick is special to — it is what makes that one case linear.
Dynamic connectivity. When edges are inserted and deleted online, recomputing bridges each time is wasteful. Holm, de Lichtenberg, and Thorup (2001) maintain full connectivity — and 2-edge-connectivity — under arbitrary updates in amortized time per operation using a hierarchy of spanning forests.5 This is the data structure behind interactive network-reliability tools and incremental mesh processing, where the graph changes faster than a from-scratch DFS could keep up.
Takeaways
- A bridge (cut edge) and an articulation point (cut vertex) are the single points of failure of a network: removing one increases the component count. Their absence is 2-edge-connectivity and 2-vertex-connectivity (biconnectivity); cut edges and vertices are the seams between biconnected components.
- DFS on an undirected graph produces only tree edges and back edges, with no cross or forward edges, so the only way out of a subtree is a back edge to an ancestor.
- The low-link is the smallest discovery time reachable from 's subtree via tree edges plus at most one back edge; compute it alongside in one recursion.
- Bridge criterion: tree edge is a bridge . Articulation criterion: a non-root is a cut vertex some child has ; the root is a cut vertex it has children. The strict-vs-nonstrict gap ( vs ) is the whole distinction.
- A single DFS reports all bridges and cut vertices (and biconnected components). Guard the parent edge by id, not the parent vertex, to stay correct under multi-edges.
Footnotes
- Skiena, §5 — Graph Traversal: edge- and vertex-connectivity, and articulation vertices as the weak points found by DFS low-links. ↩
- CLRS, Ch. 22 — Elementary Graph Algorithms (DFS): an undirected DFS yields only tree and back edges; the parenthesis/white-path structure that grounds the low-link argument. ↩
- Erickson, Ch. 6 — Depth-First Search: Tarjan's low-link computation for bridges, articulation points, and biconnected components in linear time. ↩
- Hopcroft, J. & Tarjan, R. E. (1973),
Algorithm 447: efficient algorithms for graph manipulation,
Communications of the ACM 16(6), 372–378 — biconnected components and the block-cut structure via DFS. ↩ - Holm, J., de Lichtenberg, K. & Thorup, M. (2001),
Poly-logarithmic deterministic fully-dynamic algorithms for connectivity, minimum spanning tree, 2-edge, and biconnectivity,
Journal of the ACM 48(4), 723–760. ↩
╌╌ END ╌╌