Lesson 10 of 15
Directed Cycle Detection
Cycle Detection in Directed Graphs
Detecting cycles in directed graphs is more complex than undirected ones. A back edge in undirected DFS always means a cycle — but in directed graphs, we need to distinguish a back edge (true cycle) from a cross edge (harmless).
Three-Color DFS
Track each node's state:
- White (0): unvisited
- Gray (1): currently in the DFS call stack (being explored)
- Black (2): fully explored
A cycle exists when we find a gray neighbor — a node still on the current path:
def has_cycle_directed(n, edges):
graph = {i: [] for i in range(n)}
for u, v in edges:
graph[u].append(v)
color = [0] * n # 0=white, 1=gray, 2=black
def dfs(node):
color[node] = 1 # gray: in stack
for nb in graph[node]:
if color[nb] == 1: # gray neighbor → back edge → cycle!
return True
if color[nb] == 0 and dfs(nb):
return True
color[node] = 2 # black: done
return False
for node in range(n):
if color[node] == 0:
if dfs(node):
return True
return False
Key Difference vs Undirected
Directed: 0 → 1 → 2 0 → 1 → 2 → 0
No cycle Cycle (0 turns gray again)
Undirected: 0 — 1 — 2 always has no cycle (it's just a path)
Your Task
Implement has_cycle_directed(n, edges) where edges is a list of directed edge tuples (u, v).
Pyodide loading...
Loading...
Click "Run" to execute your code.