Depth-First Search (DFS)
recursively explore graph, backtracking as necessary
parent = {s: None}
DFS-Visit(V, Adj, s):
for v in Adj[s]:
if v not in parent
parent[v] = s
DFS-Visit(V, Adj, v)
DFS(V, Adj):
parent = {}
for s in V:
if s not in parent:
parent[s] = None
DFS-Visit(V, Adj, s)
Analysis: O(E + V)
Edge Classification:
- tree edge: (parent pointer) visit new vertex via edge
- forward edge: node -> descendant in tree
- backward edge: node -> ancestor in tree
- cross edges: between two non-ancestor-related subtrees
Cycle detection:
G has a cycle <=> DFS has a back edge
Topological Sort
Reverse of DFS finishing times (time at which DFS-Visit(v) finishes)
Correctness
For any edge (u, v) — u ordered before v, i.e., v finished before u
- if u visited before v: before visit to u finishes, will visit v (via (u, v) or otherwise), v finishes before u
- if v visited before u: graph is acyclic, u cannot be reached from v, visit to v finishes before visiting u