Understanding the pseudocode in the Donald B. Johnson's algorithm
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
Donald B. Johnson's algorithm (1975) finds all elementary cycles (simple circuits) in a directed graph. It is one of the most efficient algorithms for this problem, running in O((n + e)(c + 1)) time where n is vertices, e is edges, and c is the number of cycles found. The key insight is a "blocking" mechanism that prevents redundant exploration — once a node is known not to lead to a cycle through the current start vertex, it is blocked and skipped until it is unblocked by finding a new cycle. Understanding the pseudocode requires grasping three concepts: the DFS-based circuit search, the blocking/unblocking mechanism, and the SCC-based decomposition.
High-Level Algorithm Structure
The algorithm processes each vertex as a potential starting point for cycles. It first finds the strongly connected component containing that vertex (cycles can only exist within SCCs), then searches for all cycles starting and ending at that vertex.
The CIRCUIT Function (Core DFS)
This is a depth-first search from vertex v looking for paths back to s. When the search reaches s, a cycle is found. The return value f indicates whether any cycle was found through v.
The UNBLOCK Function
When a cycle is found through vertex u, we unblock it. The set B[u] tracks vertices that should also be unblocked when u is unblocked — this cascading unblock is what makes the algorithm efficient.
Python Implementation
Blocking Mechanism Explained
The blocking mechanism prevents revisiting vertex 4 from vertex 2 when searching for cycles through vertex 1 (since 4 cannot lead back to 1). But when a cycle is found through 3, the unblock cascades to 4 via B[2], allowing future exploration.
Common Pitfalls
- Confusing blocking with visited: Blocking is not the same as a standard DFS visited flag. Blocked nodes can be unblocked later when new cycles are discovered. A visited flag in standard DFS is permanent; blocking in Johnson's algorithm is temporary and cycle-dependent.
- Not restricting to the SCC subgraph: The circuit search must only traverse edges within the strongly connected component containing
s. Searching the full graph finds paths that cannot form cycles, wasting time and producing incorrect results. - Forgetting the cascading unblock via B sets: The
B[w]sets record dependencies: "whenwis unblocked, also unblock vertices inB[w]." Skipping this cascade causes the algorithm to miss cycles because vertices remain incorrectly blocked. - Not processing vertices in order: The algorithm requires processing start vertices in ascending order and restricting the subgraph to vertices
>= s. This prevents finding the same cycle multiple times (once from each vertex in the cycle). - Self-loops as special case: A self-loop (vertex with an edge to itself) is an elementary cycle of length 1. The SCC detection must include single-vertex SCCs that have self-loops. Many SCC implementations skip single-vertex components, causing self-loops to be missed.
Summary
- Johnson's algorithm finds all elementary cycles in a directed graph in O((n + e)(c + 1)) time
- It processes each vertex as a starting point and searches for cycles within its SCC
- The blocking mechanism prevents redundant exploration: blocked vertices are skipped until new cycles make re-exploration worthwhile
- The
Bsets enable cascading unblock: when a cycle is found, all dependent vertices are unblocked recursively - The algorithm restricts search to vertices >= the current start vertex to avoid finding duplicate cycles
- Use Tarjan's algorithm to find SCCs as a preprocessing step for each iteration
Related reading
- Understanding the Recursion of mergesort
- Understanding Time complexity calculation for Dijkstra Algorithm
- Understanding Ukkonen's algorithm for suffix trees
- Unfamiliar symbol in algorithm what does ∀ mean?
- Understanding unique keys for array children in React.js
- Union-find expressed as a social network
- Union-Find or DFS which one is better to find connected component?
- Union of multiple K-minimum values sets of different sizes in the KMV algorithm

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.