These identify single points of failure: the one cable or one router whose loss splits the network. That framing is exactly how they appear in interviews.
Same disc (discovery time) and low (lowest reachable disc via the subtree + back-edges) as Day 17, but for undirected DFS we track the parent to skip the edge we came in on.
The > vs ≥ distinction is the whole subtlety: an articulation point can sit on a cycle (back-edge to itself is fine), a bridge cannot.
| Metric | Value |
|---|---|
| Time | O(V + E) — single DFS |
| Space | O(V) — disc/low arrays + recursion |
Finds all bridges. (Articulation points use the ≥ variant + root child-count.)
import java.util.*;
private int[] disc, low;
private int timer;
private List<List<Integer>> bridges;
public List<List<Integer>> findBridges(int n, List<Integer>[] adj) {
disc = new int[n]; low = new int[n];
Arrays.fill(disc, -1);
bridges = new ArrayList<>();
timer = 0;
for (int u = 0; u < n; u++) if (disc[u] == -1) dfs(u, -1, adj);
return bridges;
}
private void dfs(int u, int parent, List<Integer>[] adj) {
disc[u] = low[u] = timer++;
for (int v : adj[u]) {
if (v == parent) continue; // skip the edge we came from
if (disc[v] == -1) { // tree edge
dfs(v, u, adj);
low[u] = Math.min(low[u], low[v]);
if (low[v] > disc[u]) // bridge condition
bridges.add(Arrays.asList(u, v));
} else { // back edge
low[u] = Math.min(low[u], disc[v]);
}
}
}
u–v, the "skip parent" trick over-skips. Track the edge id instead of the parent vertex when multi-edges are allowed.| Disguise / phrasing | What's really asked | Twist to handle |
|---|---|---|
| "Critical connections / single point of failure" | Bridges | low[v] > disc[u] |
| "Critical routers / servers" | Articulation points | low[v] ≥ disc[u]; root needs ≥2 children |
| "Which links can fail without splitting the network" | Non-bridge edges | Edges on a cycle (2-edge-connected) |
| "Redundantly connected regions" | 2-edge / 2-vertex connected components | Remove bridges → components |
| "Minimum edges to add to remove all bridges" | Edge-connectivity augmentation | Bridge tree, count leaves → ⌈leaves/2⌉ |
>; articulation points use ≥. Swapping them is the classic bug.low[u] = min(low[u], disc[v]) for back-edges.