Memra

Depth-first search & edge classification

◈ 6 cards

DFS 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.

BBFCud=1 f=8vd=2 f=7wd=9 f=12xd=4 f=5yd=3 f=6zd=10 f=11B back · F forward · C cross
Solid = tree edge. Dashed: B = back (x→v reaches gray v, and the self-loop z→z — either one proves a cycle), F = forward (u→x reaches black x with u.d = 1 < x.d = 4), C = cross (w→y reaches black y with w.d = 9 > y.d = 3).
123456789101112clock(u(v(y(xx)y)v)u)(w(zz)w)u gray [1,8]w gray [9,12]Nested or disjoint — never (u (v u) v).
Each cell is one clock tick: “(u” is u.d = 1, “u)” is u.f = 8. Intervals either nest ([1,8] ⊃ [2,7] ⊃ [3,6] ⊃ [4,5], so x is a descendant of u) or stay disjoint ([9,12], so w is unrelated). A partial overlap is impossible — that is the Parenthesis Theorem.
NORMAL ~/memra/learn/comp-372/depth-first-search utf-8 LF