3.5.6 · D3Graphs

Worked examples — DFS applications — cycle detection (directed and undirected)

4,195 words19 min readBack to topic

Everything here builds on Depth-First Search as the engine. Before any example, we pin down the two algorithms, the adjacency-list input, and the exact vocabulary we'll lean on, so no symbol appears unexplained.


The scenario matrix

Every cell below is a distinct case class. The examples that follow are each labelled with the cell they cover, so together they tile the whole table.

# Case class Directed? Expected result Why it's on the list
C1 Simple back edge to an ancestor Directed Cycle The textbook Gray-hit
C2 Cross / forward edge (reaches Black) Directed No cycle The classic false-alarm to avoid
C3 2-node cycle (smallest directed) Directed Cycle Parent-trick would wrongly miss it
C4 Self-loop (1-edge cycle) Directed Cycle Degenerate 1-edge input
C5 Triangle Undirected Cycle The genuine second-path-back
C6 Tree (no extra edge) Undirected No cycle Every non-parent test must pass cleanly
C7 Two parallel edges (multigraph) Undirected Cycle v != parent alone can fail
C8 Disconnected: cycle hides in component 2 Either Cycle The "forgot to loop all components" trap
C9 Real-world: build/task dependencies Directed No cycle (DAG) Word problem → Topological Sort
C10 Exam twist: same edge set, one arrow flipped Directed flips No→Yes Tests true understanding

C1 — Directed back edge to an ancestor


C2 — Directed cross/forward edge (reaches Black, NO cycle)


C3 — Smallest directed cycle: 2 nodes


C4 — Self-loop (a 1-edge cycle)


C5 — Undirected triangle (genuine second path back)


C6 — Undirected tree (no extra edge, NO cycle)


C7 — Two parallel edges (multigraph) — where v != parent can fail


C8 — Disconnected graph, cycle hidden in component 2


C9 — Real-world word problem: build/task dependencies


C10 — Exam twist: flip one arrow, answer flips


Recall Self-test: match cell → rule

Which cell shows the parent-trick failing on a directed graph? ::: C3 (the 2-cycle ). Which cell shows v != parent being insufficient? ::: C7 (parallel/multigraph edges — need edge-index tracking). In C10, why does give no cycle but does? ::: is Black (finished descendant) when is scanned; is Gray (live ancestor) when is scanned. Which cell proves you must keep the outer for every vertex loop? ::: C8 (cycle hidden in a disconnected component). What does visited[] store in the undirected method, and what does parent hold? ::: visited[u] is True once u is entered; parent is the vertex we arrived from (which we skip once).


Connections

  • Parent topic — cycle detection — the rules these examples exercise.
  • Depth-First Search — the traversal every example runs on.
  • Topological Sort — C9's payoff: acyclic ⇔ a build order exists.
  • Union-Find (DSU) — the undirected alternative (why it doesn't fit C9's directed case).
  • Back Edges and Edge Classification — Gray-hit = back edge; Black-hit = forward/cross (C1 vs C2).
  • Strongly Connected Components — cycles are the atoms SCCs are built from.
  • Bipartite Checking — another DFS-colouring cousin.