dp p vs np ← termit.dev

Graph algorithms, step by step

Twelve algorithms that nearly every graph interview question is built from, grouped by the question they answer. Each tab explains one and runs it on a small graph you can step through: the colors, the data structures and the highlighted line of C++ move together. Every program compiles as-is and prints what the animation ends on. For telling hard problems from easy ones, see P vs NP; for problems solved by filling in a table, dynamic programming.

Breadth-first search

O(V + E) time · O(V) memory · a queue

BFS explores in rings: first every node one edge from the start, then every node two edges away, and so on. A plain first-in, first-out queue keeps the rings in order, so the first time BFS reaches a node it has used the fewest possible edges. Whenever every edge costs the same, BFS is the shortest-path algorithm.

how it works

  1. Set dist[start] = 0 and every other dist to −1 (not discovered yet). Push start into a queue.
  2. Take the node u at the front of the queue.
  3. For each neighbor v of u: if it is already discovered, skip it. Otherwise set dist[v] = dist[u] + 1, remember parent[v] = u, and push v to the back.
  4. Repeat until the queue is empty. dist[v] is now the fewest edges from start to v; following parent[] back from v and reversing gives the path itself.

why it works

The queue only ever holds two neighboring rings: nodes at distance d at the front, nodes at d + 1 behind them. So nodes leave it in order of distance. Now say v is discovered from u, at distance d. If v had a shorter path, the node just before v on it would be closer than d, would have left the queue before u, and would have discovered v first. So d + 1 is the true distance.

cost

Each node is pushed and popped once, and each edge is looked at once from each end: O(V + E) time. The queue, dist and parent take O(V) memory.

watch out

  • Mark a node when you push it, not when you pop it. Marking on pop lets the same node into the queue many times — on a big grid, that is the difference between passing and timing out.
  • BFS counts edges. With weighted edges use Dijkstra. With weights of only 0 and 1, use 0-1 BFS: a deque where 0-weight neighbors go to the front.
  • A grid is a graph: the neighbors of cell (r, c) are the four cells around it. Check bounds instead of building an adjacency list.
  • Several starting points — every rotten orange, every exit? Push them all with distance 0 before the loop. That is multi-source BFS, still O(V + E).
  • Need the answer level by level? Read q.size() at the top of each round and pop exactly that many.

practice

which one when

the questionreach fortime
Fewest edges or steps from A to BBFSO(V + E)
Shortest path, every weight 0 or 10-1 BFS, dequeO(V + E)
Shortest path, weights ≥ 0DijkstraO((V + E) log V)
Shortest path to one goal, with a distance estimateA*O(E log V) worst
Shortest path, some weights negativeBellman–FordO(V · E)
Every pair of nodes, V up to a few hundredFloyd–WarshallO(V³)
Shortest or longest path in a DAGtopo order + DPO(V + E)
Best total in exactly k moves, or within k stopsDP over (moves, node)O(k · E)
Visit everything, count components, flood fillDFS or BFSO(V + E)
Does a directed graph have a cycle?DFS, 3 states · or KahnO(V + E)
Order tasks that depend on each othertopological sortO(V + E)
Connect everything at the lowest total costKruskal · PrimO(E log E) · O(V²) dense
Are a and b connected, as edges keep arriving?union-find≈ O(1) per call
Use every edge exactly onceEuler pathO(V + E)
Which single edge or node failure disconnects it?bridgesO(V + E)
Visit every node exactly onceNP-hard · bitmask DPO(2ⁿ · n²), n ≤ 20
Two groups, no edge inside a group?BFS 2-coloringO(V + E)

words

graph
Nodes (V of them, also called vertices) joined by edges (E of them).
directed, undirected
One-way arrows versus two-way connections.
weighted
Every edge carries a number: a distance, a cost, a time.
adjacency list
adj[u] lists the neighbors of u, with weights if there are any. Most programs here use it: O(V + E) memory, against O(V²) for a matrix.
in-degree
The number of edges pointing into a node.
cycle
A path that comes back to where it started.
DAG
Directed acyclic graph: directed, no cycles. Exactly the graphs that have a topological order.
tree, spanning tree
A tree is connected with no cycles, so n nodes means n − 1 edges. A spanning tree is a tree that uses every node of a graph.