3.5.9 · D4Graphs

Exercises — Articulation points and bridges — Tarjan's low-link values

3,371 words15 min readBack to topic

Two small graphs recur below; each figure labels its vertices, edges, tree/back edges, and the critical structures so you can map the text's node names directly onto the picture.

Figure — Articulation points and bridges — Tarjan's low-link values
Figure — Articulation points and bridges — Tarjan's low-link values

Level 1 — Recognition

Recall Solution L1.1

Answer: (b). A bridge is an edge; an articulation point is a vertex. Statement (a) is the articulation-point definition, and (c) is only the root special-case test, not a definition at all.

Recall Solution L1.2

It is a back edge (an edge to an already-visited ancestor). Undirected DFS has only tree edges and back edges (no cross/forward edges). You update You use , not , because a back edge only records how high you jumped, not what that ancestor's subtree can further reach.

Recall Solution L1.3

Edge . Vertex dangles off the triangle by that one edge; the triangle itself is a cycle so none of its edges is critical. That lone edge is the bridge.


Level 2 — Application

Recall Solution L2.1

Timestamps in visit order (starting at ): for vertices .

  • Visit : the only non-parent neighbour is (already visited, ancestor) → back edge, so . ( can climb up to the node stamped .)
  • Back to : . Why the minimum? must record the highest (smallest-timestamp) ancestor reachable from 's subtree. Node alone reaches only itself (time ); but through its child the subtree already reaches time . The best of is the smaller, — so picks exactly the highest escape available.
  • Back to : . (Same logic: inherits its child's best reach.)
  • Back to : . ( is the root, it reaches itself at time , which is already the highest possible.)

Final: . Bridge test on tree edge : bridge (the subtree under never climbs as high as ). All other tree edges fail the strict test. One bridge: .

Recall Solution L2.2

From root we discover as three separate tree children (no edges connect them).

  • Root rule: has children ⇒ is an articulation point.
  • Leaves have no children, so no test can flag them; each is a degree-1 leaf whose removal disconnects nothing else. Not articulation points. Answer: only .
Recall Solution L2.3

Correct update: . If you wrongly used you'd claim can climb to timestamp — but the back edge only lets you reach itself (time ). Whatever 's subtree reaches () may go through a different branch that cannot access this way. Using over-reports reachability and can hide a genuine bridge.


Level 3 — Analysis

Recall Solution L3.1

Bridge iff ; articulation (non-root) iff .

case bridge? () AP? ()
(i) yes yes
(ii) no yes
(iii) no no

Case (ii) is the crucial gap between the tests: means 's subtree reaches itself (a back edge into ) but nothing above . The edge is therefore redundant (not a bridge), yet deleting the vertex still severs the subtree — so is an articulation point.

Recall Solution L3.2

DFS , then back edge .

  • .
  • ; this propagates up: .
  • Every tree edge has , never and never except degenerate root — check each: for parent (), ; etc.
  • Root has exactly one child () ⇒ root rule not triggered.

Answer: bridges, articulation points. Every vertex has an alternate route around the cycle — no single failure disconnects anything. This is the smallest biconnected block bigger than an edge.

Recall Solution L3.3

False. Counterexample: two triangles sharing one vertex — vertices forming a triangle and forming another, sharing .

  • Vertex is an articulation point (remove it and the two triangles fall apart).
  • But no edge is a bridge: each edge sits inside a triangle, so cutting any single edge leaves its endpoints still connected the other way around.

So articulation points can exist with zero bridges. (The converse does hold in a useful sense: every bridge's endpoints, if non-leaf, are articulation points.)


Level 4 — Synthesis

Recall Solution L4.1

DFS goes (first copy = tree edge). At , the second copy leads back to = the parent. The naïve rule if neighbour == parent: skip throws it away, so never records a back edge to and stays falsely flagged as a bridge. But the two edges form a tiny cycle; neither is truly critical.

What "edge id" means and how to assign it. Store the graph as an edge list and number the edges in the order you read them. For an undirected edge you push it into both endpoints' adjacency lists carrying the same id — e.g. adj[u].append((v, id)); adj[v].append((u, id)). So the two parallel edges get different ids (say and ), even though they share the same endpoints.

Corrected code. Pass the id of the edge you descended as parentEdge (initially ). In the loop, iterate over (v, id) pairs and skip a neighbour only when id == parentEdge, not when v == parent:

def dfs(u, parentEdge):
    for (v, eid) in adj[u]:
        if eid == parentEdge:      # skip the ONE edge we came down
            continue
        ...                        # tree edge → recurse; else back edge

Now the second parallel edge (a different id) is correctly treated as a back edge, giving , so fails → correctly not a bridge.

Recall Solution L4.2

Using , from L2.1:

  • Bridges: tree edge : ⇒ bridge. No others. Bridges .
  • Articulation points:
    • Root : only child ⇒ root rule fails ⇒ not an AP.
    • Vertex (non-root), child : AP.
    • Vertex , child : , i.e. is false ⇒ not AP.
    • Vertex : leaf, no children ⇒ not AP. Articulation points .
Recall Solution L4.3

Two triangles sharing a single vertex (the L3.3 graph): edges 6 edges, 5 vertices.

  • AP: only vertex (shared corner). ✔ exactly one.
  • Bridges: none — every edge lies inside a triangle. ✔ exactly zero. You cannot do it with fewer edges: to have zero bridges every edge must lie on a cycle, so you need at least two cycles (a single cycle has no AP), and the smallest cycles are triangles ( edges each), sharing one vertex to save an edge → .

Level 5 — Mastery

Recall Solution L5.1

Time. The DFS visits each vertex exactly once (guarded by disc[u] == -1), doing work at entry. Across the whole run, the inner loop iterates over every adjacency-list entry; each undirected edge appears in exactly two lists, so total loop iterations , each (a , a compare, and one insert into the articulation-point collection). Why the AP insert is . Store the articulation points in a boolean array isAP of size (indexed by vertex number), not a hash set. Marking isAP[u] = True is a direct array write — a genuine worst-case operation with no hashing and no resizing. (If you prefer a hash set, the insert is amortised ; the array makes it unconditional, closing the gap.) Duplicate marks (a vertex flagged by several children) are harmless idempotent writes. Summing: vertex work edge work . Space. Arrays are each size ; recursion depth . Total extra memory . (Same asymptotics as plain Depth-First Search — the low-link bookkeeping adds only constants.)

Recall Solution L5.2

All three ask "what is the highest ancestor a subtree can climb back to?" and store it as low. For undirected APs/bridges you allow tree edges + one back edge and compare low[v] against disc[u] ( / ). For directed SCCs the graph is directed, so you also track an on-stack flag and pop a component when — the low-link marks the root of a strongly connected block instead of a cut. Contracting every 2-edge-connected component to a node and keeping only bridges yields the bridge tree, a tree because bridges are exactly the edges not on any cycle. One DFS, one low idea, three structures.

Recall Solution L5.3

Edges now: . DFS .

  • .
  • : back edge .
  • : children give ; also back-neighbour (ancestor) ⇒ .
  • : .
  • : .
  • .

Bridges: check tree edges — : ? No. : ? No. : ? No. No bridges. APs: : child , ? No. : child , ? No. Root : one child ⇒ no. No articulation points. Adding created a second escape route, destroying the bridge and the cut vertex from Graph A.

Recall One-line self-check

When does a tree edge pass the bridge test but fail the AP test? ::: When is the root with only that one child — then can hold (bridge) yet the root rule needs children (no AP).