Worked examples — Link state routing — OSPF, Dijkstra
The scenario matrix
Think of each row as a type of trap a question can spring. Every worked example below is tagged with the cell it covers.
| # | Case class | What's tricky | Covered by |
|---|---|---|---|
| C1 | Plain positive graph | baseline, one clear answer | Example 1 |
| C2 | Tie in tentative distances | two nodes share the minimum — which to pick? | Example 2 |
| C3 | Two equal-cost shortest paths (ECMP) | OSPF keeps both | Example 3 |
| C4 | Disconnected / unreachable node | some stays | Example 4 |
| C5 | Zero-cost edge (degenerate) | , is greedy still safe? | Example 5 |
| C6 | Negative edge (Dijkstra FAILS) | greedy finalizes too early | Example 6 |
| C7 | Link failure → re-flood → recompute | the map changes, routes change | Example 7 |
| C8 | Real-world word problem | translate "delays" into a graph | Example 8 |
| C9 | Exam twist: directed graph | Example 9 |
Example 1 — C1: the baseline positive graph
Forecast: Guess the cheapest way from to before reading on. Is it the direct-looking , or a sneaky detour through ?

- Init. , everything else , finalized set . Why this step? We must start knowing nothing except that the source is away from itself.
- Pick (min ). Relax its edges: , . Why this step? Greedy invariant: the smallest tentative distance is already final, so is safe to lock, then we update its neighbours.
- Pick (min ). Relax: , . Why this step? now has the smallest tentative value. Relaxing improves from to (path beats direct ).
- Pick (min ). Relax: . Why this step? Going costs , cheaper than .
- Pick (min ). All finalized.
Verify: Enumerate the three simple paths to : , , . Minimum is . ✓ Path: .
Example 2 — C2: a tie for the minimum
Forecast: After finalizing , both and sit at . Does it matter whether we grab or first?
- Init & pick . Relax: , . A tie. Why this step? Standard init, then is the unique minimum.
- Break the tie arbitrarily — pick . Relax: . Why this step? When two nodes share the minimum, Dijkstra's correctness does not depend on which you pick; both are already final because their tentative value is smallest.
- Pick (still , final). Relax: . No change. Why this step? 's distance was already finalized-worthy; relaxing just confirms .
- Pick (). Done.
Verify: Had we picked first, would compute then be confirmed by — identical. Both orderings give , . ✓ Tie-breaking never changes the distances (it may change which path is stored).
Example 3 — C3: two equal-cost shortest paths (OSPF's ECMP)
Forecast: One next-hop, or two?
- List the shortest paths to . and . Why this step? ECMP keeps every path whose total cost equals the minimum — here both equal .
- Read off first hops. Path 1's first hop is ; path 2's is . Why this step? The forwarding table stores destination → next-hop (from the parent note). Two equal paths ⇒ two next-hops.
- Forwarding entry.
Dest D → next-hop {B, C}, cost 5— traffic to can be split across and . Why this step? This is exactly OSPF's load-balancing feature; a distance-vector protocol without ECMP would keep only one. See OSPF Areas for how OSPF scales this.
Verify: Both paths cost ; there are exactly equal-cost paths, hence next-hops. ✓
Example 4 — C4: an unreachable node
Forecast: A number, or a symbol?
- Init. , . Why this step? Standard start; means "no known path yet."
- Pick , relax: . Pick , relax: . Why this step? The reachable part fills in normally.
- Now pick the minimum unfinalized. Only remains, at . Why this step? No edge ever relaxed , so nothing lowered it.
- Result: — is unreachable; no routing-table entry is created for it. Why this step? A finite algorithm cannot invent a path that the topology graph does not contain.
Verify: No sequence of edges connects to , so the true shortest distance is , matching the algorithm. ✓
Example 5 — C5: a zero-cost edge (degenerate but legal)
Forecast: Does a zero-weight edge break the greedy invariant like a negative one would?
- Init & pick . Relax: , . Why this step? The edge has cost , so is exactly as far as .
- Pick (min , tied with which is already done). Relax: . No change. Why this step? Greedy needs weights — and is , so finalizing at is safe. A later edge can never lower an already-final distance because all remaining edges add .
- Pick (). Done.
Verify: (a free hop), . Paths and both cost . Zero weights preserve the non-negativity precondition, so no failure. ✓
Example 6 — C6: a negative edge that BREAKS Dijkstra
Forecast: Dijkstra will "finalize" early. Guess whether the finalized value is the true shortest distance.

- Init & pick . Relax: , . Why this step? Standard start.
- Pick (min ) and finalize it. Why this step? Greedy assumes the smallest tentative value is final. This is the fatal assumption when a negative edge exists.
- Pick (). Relax : would become . But is already finalized, so Dijkstra never revisits it. Why this step? This is precisely where Dijkstra loses correctness — it refuses to improve a locked node.
- Dijkstra's output: . True shortest: … equal here, but consider the general danger below.
True computation (correct tool): the shortest distance to is . In this instance both happen to be , so the number matches — but the path Dijkstra records () is not the only optimum, and if were then would be missed entirely.
Verify: With : . With a hypothetical : true , but Dijkstra still reports — wrong. Negative weights ⇒ use Bellman–Ford Algorithm, never Dijkstra. ✓
Example 7 — C7: a link fails, LSPs re-flood, routes recompute
Forecast: By how much does the distance to jump when the good link dies?
- Before failure — run Dijkstra. Pick : , . Pick : . via . Why this step? Baseline shortest path over the healthy topology.
- Link fails. notices via missing HELLOs, builds a new LSP with a higher sequence number, floods it. Why this step? From the parent: the newest LSP (highest sequence) replaces the old map on every router. See Routing Table vs Forwarding Table for what gets rebuilt.
- Every router rebuilds the graph — edge is gone — and reruns Dijkstra. Pick : , . Pick : . Now via . Why this step? With the fast link removed, the only route to is the expensive side.
- Result: jumps from to ; next-hop for changes from to .
Verify: Before: . After removing : only remains. ✓
Example 8 — C8: a real-world word problem
Forecast: Straight down , or the two-short-hops route through ?
- Translate to a graph. Latencies are edge weights (all positive ⇒ Dijkstra is valid). Directed because a one-way latency need not equal the reverse. Why this step? "Minimise total delay" = "shortest path with weights = delays." This is the standard OSPF trick: cost = a link metric.
- Run Dijkstra from . Pick : , . Why this step? Finalize the source, relax its out-edges.
- Pick (min ). Relax: ; . Why this step? (=) beats the direct (=).
- Pick (min ). Relax: . Why this step? beats .
- Pick (). Done.
Verify: Candidate routes: ; ; . Minimum ms via . ✓ (Units: all terms are ms, summed ⇒ answer in ms.)
Example 9 — C9: exam twist — directed asymmetric graph
Forecast: Will the cheap edge help lower ?
- Init & pick . Relax out-edges of only: , . Why this step? In a directed graph you relax only edges pointing away from the current node. The edge is irrelevant to reaching or from .
- Pick (min ). Relax 's out-edges: (ignore, done), . Why this step? beats direct .
- Pick (min ). Relax : . No change. Why this step? The cheap edge cannot help — reaching already cost , so .
- Result: , .
Verify: Shortest to : direct (the reverse edge and the detour are both longer). Shortest to : . ✓ Direction matters: never enters the computation.
Active recall
Recall Which scenarios break Dijkstra, and what replaces it?
- Negative edge weights ::: Dijkstra may finalize a node too early and miss a cheaper later path ⇒ use Bellman–Ford Algorithm.
- Zero-weight edge ::: Fine — keeps the greedy invariant valid.
- Tie in tentative distances ::: Pick either; final distances are identical (path stored may differ).
- Unreachable node ::: Its stays ; no forwarding entry.
- Two equal-cost shortest paths ::: OSPF keeps both (ECMP), two next-hops.
Connections
- Link state routing — OSPF, Dijkstra — the topic this deep-dives
- Dijkstra's Algorithm — the core algorithm exercised here
- Bellman–Ford Algorithm — the fix for Example 6's negative edge
- Distance Vector Routing — the alternative family
- Flooding — how the failed-link LSP in Example 7 propagates
- OSPF Areas — how ECMP (Example 3) scales in real OSPF
- Routing Table vs Forwarding Table — what recomputation rebuilds