Depth-first search & edge classification
◈ 6 cardsDFS timestamps, the parenthesis structure, the four edge types, and cycle detection via back edges.
Depth-first vs breadth-first
Where BFS explores a single source level by level with a queue, depth-first search plunges as deep as possible before backtracking, restarts from any remaining white vertex, and so produces a depth-first forest of possibly several trees. DFS runs in by the same aggregate argument as BFS.
DFS's real output is two timestamps per vertex: (discovery, when is grayed) and (finish, when is blackened). A global clock ticks before each event, so all timestamps are distinct integers in . The interval is exactly the time stays gray.
The parenthesis structure
Parenthesis Theorem (20.7). For any two vertices, their intervals and are either disjoint (neither is an ancestor of the other) or nested (one is a descendant of the other). They never partially overlap — exactly like balanced parentheses. Corollary: is a proper descendant of iff .
Four edge types
Classify an edge by the colour of the first time you explore it:
- Tree edge — is white: is discovered via this edge (a child in the DFS tree).
- Back edge — is gray: is an ancestor of . A self-loop is a back edge.
- Forward edge — is black and : is a deeper descendant, but not via this edge.
- Cross edge — is black and : and are unrelated by ancestry.
In an undirected graph only tree and back edges occur (Theorem 20.10).
Cycle detection — the punchline
A directed graph has a cycle iff a DFS produces a back edge (an edge to a gray vertex). So cycle detection is free: while exploring, if any neighbour is gray, you found a cycle. This single fact drives both topological sort and SCC in the next lesson.
Worked example
On the directed graph , a DFS visiting neighbours in sorted order discovers . The edge hits gray (an ancestor of ) — a back edge — so the graph has a cycle. The self-loop is a back edge too.