Finding bridges in graph without recursion
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
A bridge (or cut-edge) in an undirected graph is an edge whose removal disconnects the graph (or increases the number of connected components). The classic algorithm by Tarjan finds bridges using DFS with disc[] and low[] arrays. The recursive version is straightforward but can cause stack overflow on large graphs. An iterative version simulates the DFS call stack explicitly, achieving the same O(V + E) time complexity without recursion depth limits.
Recursive Bridge Finding (Tarjan's Algorithm)
The recursive version for reference:
This works but fails on graphs with thousands of vertices due to Python's default recursion limit of 1000.
Iterative Bridge Finding
The iterative version uses an explicit stack to simulate DFS:
How It Works
The key insight is that the DFS recursion stack is simulated explicitly:
- Push the starting node with an iterator over its neighbors
- For each node on the stack, advance to the next unvisited neighbor
- When a neighbor is visited (tree edge), push it onto the stack
- When a neighbor is already visited (back edge), update
low[u] - When all neighbors are exhausted (
StopIteration), pop the node and propagatelowvalues to the parent - Check the bridge condition (
low[v] > disc[u]) during backtracking
Example Usage
Handling Multigraphs (Parallel Edges)
The basic algorithm breaks with parallel edges (multiple edges between the same pair). Track edge indices instead of just parent nodes:
Performance
Both recursive and iterative versions have the same time and space complexity:
| Metric | Complexity |
| Time | O(V + E) |
| Space | O(V + E) for adjacency list + O(V) for stack |
The iterative version avoids Python's recursion limit and uses heap memory (which is much larger) instead of the call stack.
Common Pitfalls
- Not handling disconnected graphs: The algorithm must loop over all vertices and start DFS from each unvisited one. A single DFS call from vertex 0 misses components not connected to vertex 0.
- Using parent node instead of parent edge for multigraphs: In graphs with parallel edges between u and v, checking
v != parent[u]incorrectly skips valid back edges. Track the edge index of the parent edge instead. - Forgetting to propagate
lowvalues during backtracking: When popping a node from the stack, itslowvalue must be propagated to its parent. Missing this step means the parent never learns about back edges in the subtree, causing false bridge detections. - Modifying the iterator during iteration: The stack stores iterators over neighbor lists. If the graph's adjacency list is modified during the algorithm, iterators become invalid. Build the graph before starting the algorithm.
- Python's recursion limit: Python defaults to 1000 recursive calls. The recursive Tarjan's algorithm crashes on graphs with more than 1000 vertices. Use the iterative version or
sys.setrecursionlimit()(less safe).
Summary
- A bridge is an edge whose removal disconnects the graph
- Tarjan's algorithm finds all bridges in O(V + E) using
disc[]andlow[]arrays - The iterative version simulates the DFS call stack with an explicit stack of
(node, neighbor_iterator)pairs - An edge (u, v) is a bridge if
low[v] > disc[u](no back edge from v's subtree reaches u or above) - Use edge indices instead of parent nodes to correctly handle multigraphs
- The iterative version avoids stack overflow on large graphs (10K+ vertices)

