Topological Sort (Graph)
Order tasks so every dependency comes before its dependent. Impossible if a cycle exists — and the algorithm detects cycles for free. Courses, build systems, package managers — all topo sort.
A cycle makes linear ordering impossible. Kahn's algorithm produces the order and detects cycles in the same O(V+E) pass — no extra work.
The cycle detection is free: after Kahn's finishes, if len(result) < n, some nodes were never dequeued — they're stuck in a cycle with non-zero in-degrees. This single check replaces a separate cycle-detection DFS entirely.
Kahn's (BFS) vs DFS Post-Order
Kahn's is easier to implement. DFS is more elegant but harder to debug.
The 3-Step Framework
Build graph → compute in-degrees → Kahn's BFS → cycle check.
Parse prerequisites/edges. Build adjacency list (src → [dests]). Count how many edges point into each node (in-degree). Both take O(E) time and O(V+E) space.
graph = defaultdict(list)
in_degree = [0] * n
for dest, src in prerequisites:
graph[src].append(dest)
in_degree[dest] += 1Seed queue with all 0-in-degree nodes. Pop → add to result → for each neighbor, decrement in-degree → if neighbor's in-degree hits 0, enqueue. Result grows one node at a time. Time: O(V+E).
queue = deque(i for i in range(n)
if in_degree[i] == 0)
while queue:
node = queue.popleft()
result.append(node)
for nb in graph[node]:
in_degree[nb] -= 1
if in_degree[nb] == 0:
queue.append(nb)If the result contains all n nodes, the DAG has a valid topological order. If not, some nodes were stuck (their in-degree never reached 0 because they're in a cycle). Return result or [] based on len(result) == n.
return result if len(result) == n else [] # For can-all-tasks-complete: return len(result) == n # True/False # For lexicographic order: # Use heapq.heappush/heappop instead of deque
Pattern Recognition
'prerequisite', 'dependency', 'ordering', 'schedule' → topological sort.