11.2 Topological Sort & Directed Cycle Detection
Understand what a Directed Acyclic Graph (DAG) and Indegree are, and how Kahn's Algorithm orders tasks with prerequisites or detects deadlocks.
1. What Is Topological Sort?
Suppose you are registering for university classes or building software packages where Task A must be finished before Task B can start (A -> B).
A Topological Sort takes a Directed Graph and lines up all nodes in a valid sequence [u1, u2, ..., uN] such that for every directed arrow A -> B, A appears before B.
(Note: If the graph has a directed cycle like A -> B -> A, a valid ordering is impossible! A directed graph with no cycles is called a DAG — Directed Acyclic Graph.)
2. Why Do We Need It & How Does Kahn's Indegree Algorithm Work?
What Is indegree?
The indegree of a node v is simply how many prerequisites (incoming arrows) v is still waiting on.
- If
indegree[v] == 0, nodevhas zero unmet prerequisites — it is ready to take right now!
Kahn's BFS Algorithm in 4 Simple Steps
- Build the directed adjacency list
adj[pre].append(course)and countindegree[course] += 1. - Push every node with
indegree == 0into a FIFO Queue. - While the queue is not empty: pop
u, adduto yourorderlist, and for each neighborvinadj[u], subtract1fromindegree[v](because prerequisiteuis now done!). The momentindegree[v] == 0, pushvinto the queue! - At the end, check
len(order) == n: if fewer thannnodes were processed, a cycle locked the remaining nodes!
Alternative Approach: 3-Color DFS Cycle Detection (0 = Unvisited, 1 = Visiting, 2 = Done)
Besides Kahn's BFS, interviewers also love asking how to detect a cycle in a Directed Graph using recursion (DFS):
- Why isn't a normal
visitedset enough for directed graphs? Because ifA -> CandB -> C, visitingCtwice from two different branches is not a cycle! - A cycle only happens if you run into a node that is currently still on your active recursion stack!
- Track
state[u]:0(Unvisited): Haven't toucheduyet.1(Visiting / On Current Path): Currently exploringu's descendants. If you see an edge to a node withstate == 1, you found a back-edge cycle!2(Completed / Safe): Finished exploringuand all its descendants with zero cycles; future visits can skipuinO(1).
Interactive Step-by-Step Trace: Kahn's Indegree Queue (Course Schedule)
Resolve prerequisites 0 → 1 → 2 and 0 → 2 using indegrees:
Course 0 has no prerequisites (indegree 0), so we can take it immediately!
3. Basic Operations & Walkthroughs (All 4 Languages)
from collections import deque
def can_finish(num_courses: int, prerequisites: list[list[int]]) -> bool:
adj = [[] for _ in range(num_courses)]
indegree = [0] * num_courses
for course, pre in prerequisites:
adj[pre].append(course)
indegree[course] += 1
# Start with all courses that have 0 prerequisites
q = deque([i for i in range(num_courses) if indegree[i] == 0])
completed = 0
while q:
curr = q.popleft()
completed += 1
for nxt in adj[curr]:
indegree[nxt] -= 1
if indegree[nxt] == 0:
q.append(nxt)
return completed == num_courses4. Core Interview Patterns & Common Traps
Use whenever tasks/courses/words have directed dependencies (A must come before B) and you need a valid linear order or need to check for circular deadlocks.
q = deque([u for u in range(n) if indegree[u] == 0])
order = []
while q:
u = q.popleft()
order.append(u)
for v in adj[u]:
indegree[v] -= 1
if indegree[v] == 0:
q.append(v)
return order if len(order) == n else [] # Empty if a cycle exists!| Operation / Pattern | Time | Space | Notes |
|---|---|---|---|
| Kahn's Topological Sort (BFS) | O(V + E) | O(V + E) | Processes every vertex and directed edge at most once |
5. Practice On Your Own (Curated Submodule Problems)
| Status | Problem | Difficulty | Complexity | Hint? | Links & Notes |
|---|---|---|---|---|---|
Course Schedule Topological Sort (Kahn's Algorithm) | Medium | T: O(V + E) S: O(V + E) |