Chapter 29 — Key Takeaways

A one-page reference for weighted graphs and shortest paths. Reread before an exam or interview.


Core definitions

Term Definition
Weighted graph $G=(V,E)$ with a weight function $w\colon E \to \mathbb{R}$; $w(u,v)$ = weight of edge $u\to v$
Path weight (length) $w(p)=\sum_{i=1}^{k} w(v_{i-1},v_i)$ for path $v_0,\dots,v_k$ — sum of edge weights, not edge count
Shortest path A path of minimum weight between two vertices (need not be unique)
Shortest-path distance $\delta(u,v)$ Weight of a shortest $u\to v$ path; $\infty$ if none; $\delta(u,u)=0$
Relaxation if dist[u]+w < dist[v]: dist[v]=dist[u]+w; prev[v]=u
Tentative distance dist[v] Best path weight to $v$ found so far; starts $0$ at source, $\infty$ elsewhere; only decreases
Priority queue ADT with insert + extract_min (returns smallest-key item); heap-backed (Ch. 31)
Negative cycle Cycle with negative total weight ⇒ affected $\delta = -\infty$, shortest paths undefined
Shortest-path tree Tree of prev pointers rooted at source; every shortest path from $s$ lies in it

Two problems: SSSP (single-source: all $\delta(s,v)$) — Dijkstra, Bellman-Ford. APSP (all-pairs: all $\delta(u,v)$) — Floyd-Warshall.


Relaxation — the universal primitive

$$\text{if } \text{dist}[u]+w(u,v) < \text{dist}[v]:\quad \text{dist}[v]\leftarrow \text{dist}[u]+w(u,v),\ \ \text{prev}[v]\leftarrow u$$

  • Safety: relaxation never sets dist[v] below $\delta(s,v)$ ⇒ any final value = weight of a real path. Every algorithm in this chapter is just "relax edges in some order."
  • Order of relaxation = the whole difference between the algorithms.

The three algorithms

Algorithm Solves Neg. edges? Neg.-cycle detect? Time Space Strategy
Dijkstra SSSP ❌ no ❌ no $O(E\log V)$ $O(V)$ greedy: extract-min unfinalized, relax its out-edges
Bellman-Ford SSSP ✅ yes ✅ yes $O(VE)$ $O(V)$ relax ALL edges $|V|-1$ times, + 1 detector pass
Floyd-Warshall APSP ✅ yes ✅ (neg. diagonal) $\Theta(V^3)$ $\Theta(V^2)$ DP over allowed waypoints; k loop outermost

Dijkstra skeleton

  1. dist[s]=0, all others $\infty$; push (0,s).
  2. Pop min (d,u); if d>dist[u] skip (stale). Else relax every out-edge of u, pushing improved (dist[v],v).
  3. dist holds $\delta(s,\cdot)$; prev gives the shortest-path tree. - Lazy deletion: push duplicates on improvement; skip stale pops with if d>dist[u]: continue.

Bellman-Ford skeleton

  1. dist[s]=0, others $\infty$.
  2. Repeat $|V|-1$ times: relax every edge.
  3. One more pass: any edge still relaxable ⇒ negative cycle reachable ⇒ return "undefined".

Floyd-Warshall recurrence

$$D_{k+1}[i][j]=\min\big(D_k[i][j],\ D_k[i][k]+D_k[k][j]\big),\qquad D_0[i][j]=w(i,j),\ D_0[i][i]=0.$$ Negative $D[i][i]$ after completion ⇒ negative cycle through $i$.


"When to use what" decision aid

Situation Use
One source, non-negative weights (distances, times, costs) Dijkstra
One source, negative edges possible Bellman-Ford
Need to detect a negative cycle / arbitrage Bellman-Ford (detector pass)
All pairs, dense graph, small–medium $V$ Floyd-Warshall
All pairs, sparse graph Dijkstra from every vertex ($O(VE\log V)$)
Unit weights only (every edge = 1) BFS (Ch. 28), $O(V+E)$ — Dijkstra is overkill
Single source→target on a map, want speed A* (Dijkstra + admissible heuristic)

Why Dijkstra is correct (the proof in one frame)

  • Invariant: when a vertex $u$ is finalized, dist[u] $=\delta(s,u)$ already.
  • Proof shape: contradiction. Let $u$ = first vertex finalized with dist[u] $>\delta(s,u)$. On a true shortest path to $u$, let $y$ = first unfinalized vertex, $x$ its (finalized) predecessor. Then:
  • $\text{dist}[y] = \delta(s,y)$ (relaxing $(x,y)$ when $x$ finalized; prefix is shortest)
  • $\delta(s,y) \le \delta(s,u)$ ← only step using $w \ge 0$
  • $\text{dist}[u] \le \text{dist}[y]$ (greedy chose $u$ over $y$)
  • Chain: $\text{dist}[u] \le \text{dist}[y] = \delta(s,y) \le \delta(s,u)$ — contradicts $\text{dist}[u]>\delta(s,u)$. $\blacksquare$
  • 🚪 Threshold: a greedy algorithm can be provably optimal — find the invariant the greedy choice preserves (reused for MST cut property, Ch. 32).

Why Bellman-Ford's $|V|-1$: a shortest path with no negative cycle is simple (≤ $|V|-1$ edges); path-relaxation property — after $k$ passes, all $\le k$-edge shortest distances are exact.


Common pitfalls

Pitfall Reality
Finalize a vertex on discovery (first finite dist) Only safe to finalize the global min unfinalized vertex
Run Dijkstra with negative edges Wrong answers — greedy commits before seeing a cheaper negative route. Use Bellman-Ford
"Add a constant to remove negatives, then Dijkstra" Penalizes paths by edge count; can change which path is shortest. Wrong
Shortest = fewest edges No — shortest = minimum total weight; BFS solves only the unit-weight case
Floyd-Warshall with i or j outside k Wrong; k (waypoint) must be the outermost loop
Forget the detector pass in Bellman-Ford Silently returns garbage on a negative cycle
Drop if d > dist[u]: continue in heap Dijkstra Still correct, but reprocesses stale entries (slower)

Complexity at a glance

Operation / algorithm Cost
One relaxation $O(1)$
Heap insert / extract_min $O(\log V)$
Dijkstra (binary heap) $O((V+E)\log V) = O(E\log V)$
Dijkstra (array / dense) $O(V^2)$
Bellman-Ford $O(VE)$
Floyd-Warshall $\Theta(V^3)$ time, $\Theta(V^2)$ space
Path reconstruction (follow prev) $O(\text{path length})$

Real-world map

System Graph Algorithm
GPS navigation intersections / roads / travel times (≥ 0) Dijkstra → A* + preprocessing
Link-state routing (OSPF) routers know whole map Dijkstra locally
Distance-vector routing (RIP) routers know only neighbors distributed Bellman-Ford
Currency arbitrage detection currencies / trades / log-rates Bellman-Ford negative-cycle detector

Toolkit increment (dmtoolkit/graphs.py)

dijkstra(g, s) -> (dist, prev)   # SSSP, non-negative weights; raises ValueError on negative edge
  • Returns both distances and predecessors (so callers recover routes, not just lengths).
  • Raises on a negative weight rather than silently returning a wrong answer (correctness > plausibility).
  • code/ also ships bellman_ford(vertices, edges, source) for the negative-edge case.
  • Toolkit so far: logic, sets, relations, combinatorics, recurrences, probability, numbertheory, crypto, coding, graphs (Graph, bfs, dfs, dijkstra).