Worked examples — Bellman-Ford algorithm — DP approach, negative cycles detection, O(VE)
The scenario matrix
Every Bellman-Ford problem lands in one of these cells. Our examples below are labelled with the cell they hit, so together they cover the whole table.
| # | Case class | What's special | Example |
|---|---|---|---|
| A | All-positive edges | Dijkstra would also work; sanity baseline | Ex 1 |
| B | Negative edge, no cycle | The reason Bellman-Ford exists | Ex 2 |
| C | Order matters in a pass | Bad edge order needs full passes | Ex 3 |
| D | Negative cycle reachable from source | Detection must fire | Ex 4 |
| E | Negative cycle not reachable from source | Detection must stay silent | Ex 5 |
| F | Unreachable vertex () | The dist[u] != inf guard |
Ex 6 |
| G | Degenerate: 1 vertex, 0 edges | Base case only | Ex 7 |
| H | Zero-weight cycle (limiting between and ) | Must not be flagged | Ex 8 |
| I | Real-world word problem | Currency / travel tolls | Ex 9 |
| J | Exam twist: "which pass first settles ?" | Reasoning about convergence speed | Ex 10 |
Note the two limiting boundaries we deliberately test: cell H sits exactly on the fence (cycle sum , neither negative nor positive) and cell G is the smallest legal graph. Never skip the boundaries — that is where wrong code dies.
Ex 1 — Cell A: all-positive baseline
Forecast: guess the four final numbers before reading on. (Hint: is going cheaper than direct?)

- Init.
dist = [0, ∞, ∞, ∞]. Why this step? With edges you can only sit at the source, cost ; everything else is unknown, i.e. . - Pass 1, edges in listed order.
- : →
dist[1]=2. - : →
dist[2]=6. - : →
dist[2]=5. (the detour wins!) - : →
dist[3]=7. - : →
dist[3]=6. Why this step? One sweep already propagated cost outward two hops because the edges happened to be in a friendly order.
- : →
- Pass 2. Check every edge again → nothing improves.
Why this step? When a full pass changes nothing, the early-exit
breakfires; distances are final.
Answer: dist = [0, 2, 5, 6].
Verify: Cheapest to is (beats direct ). Cheapest to is (beats ). ✓
Ex 2 — Cell B: negative edge, no cycle
Forecast: the road pays you . Does that make reaching cheaper than the direct ?
- Init.
dist = [0, ∞, ∞, ∞]. - Pass 1.
- :
dist[1]=4. - :
dist[2]=5. - : →
dist[2]=1. Why? the negative edge undercuts the direct route. - : →
dist[3]=3.
- :
- Pass 2. No edge improves → converged. Why this step? Confirms nothing negative loops back; this is a legit finite answer.
Answer: dist = [0, 4, 1, 3].
Verify: ; then . No cycle exists (edges only go "forward"), so distances are meaningful. ✓ This is the exact scenario Dijkstra would mishandle, because it would finalize dist[2]=5 before ever seeing the cheaper negative-edge route — see Dijkstra's Algorithm.
Ex 3 — Cell C: edge order forces multiple passes
Forecast: same final answer as Ex 2 — but how many passes until it settles now?

- Pass 1 (this bad order):
- :
dist[2]is → guard blocks it, no change. - :
dist[1]is → blocked. - : →
dist[2]=5. - : →
dist[1]=4. Result after pass 1:[0, 4, 5, ∞]. Why worse? The edges that use new info came before the edges that produced it.
- :
- Pass 2.
- : →
dist[3]=7. - : →
dist[2]=1. - , : no change.
Result:
[0, 4, 1, 7].
- : →
- Pass 3.
- : →
dist[3]=3. Result:[0, 4, 1, 3]. Now it matches Ex 2.
- : →
Answer: dist = [0, 4, 1, 3] — identical, but it needed 3 passes () instead of 1.
Verify: Same numbers as Ex 2 ✓. This is why we never trust a lucky order: worst case needs the full passes. The final answer is order-independent; the speed is not.
Ex 4 — Cell D: negative cycle reachable → DETECT
Forecast: loop sums to . Can any finite answer survive?

- Init.
dist = [0, ∞, ∞]. Here , so we do settle passes. - Pass 1. :
dist[1]=1. : →dist[2]=0. : →dist[0]=-1. Why this step? The cycle already dragged the source's own cost below zero — a red flag. - Pass 2. Everything drops again:
dist[1]=0,dist[2]=-1,dist[0]=-2. Why this step? Each lap of the loop subtracts ; the values never stop. - Extra pass (the ). : still relaxes (? recompute with current) → some edge still improves. Why this step? After passes everything that can settle has settled. A still-relaxable edge can only mean a negative cycle.
Answer: return None — negative cycle reachable from source.
Verify: Cycle weight . Looping it times gives cost , so no finite shortest distance exists → the flag is correct, not the numbers. See Negative Weight Cycles. ✓
Ex 5 — Cell E: negative cycle NOT reachable → stay silent
Forecast: there is a negative cycle in the graph. Will Bellman-Ford flag it?
- Init.
dist = [0, ∞, ∞, ∞]. - All passes. Only ever relaxes (
dist[1]=2). Edges and havedist[2]=dist[3]=∞→ guard blocks them forever. Why this step? Source has no path into , so their distances stay and the loop is never entered. - Extra pass. No edge relaxes → no cycle reported.
Answer: dist = [0, 2, ∞, ∞]. Cycle not detected.
Verify: Bellman-Ford only detects cycles reachable from the source — this is the second parent-note mistake made concrete. To catch all cycles you'd add a virtual source with -weight edges to every vertex (then become reachable). ✓
Ex 6 — Cell F: the dist[u] != inf guard in action
Forecast: without the guard, would that huge edge corrupt dist[1]?
- Init.
dist = [0, ∞, ∞]. - Relax :
dist[1]=3. - Relax :
dist[2]is . Computing is still , and is false, so no change even without a guard in Python — but in a fixed-width integer language, "INF + (−100)" can wrap around to a huge negative and wrongly overwritedist[1]. Why this step? The explicitif dist[u] != infcheck exists to stop that overflow bug.
Answer: dist = [0, 3, ∞].
Verify: has no incoming path from source, so it stays ; 's only reachable route is the direct . ✓
Ex 7 — Cell G: degenerate single vertex
Forecast: how many passes is here?
- Init.
dist = [0]. - Settle passes: passes → the loop body never runs.
- Extra pass: no edges → nothing relaxes → no cycle.
Answer: dist = [0].
Verify: The distance from a node to itself is ; with no edges nothing else exists. The boundary correctly does zero work. ✓ This confirms the loop bound is inclusive-safe at the smallest input.
Ex 8 — Cell H: zero-weight cycle (the exact fence)
Forecast: a -cost loop is neither profit nor loss. Should the detector fire?

- Init.
dist = [0, ∞, ∞]. → 2 settle passes. - Pass 1. :
dist[1]=2. : →dist[2]=0. : , and is false → no change. - Pass 2. No edge improves.
- Extra pass. : ? No. Nothing relaxes → no cycle reported.
Answer: dist = [0, 2, 0], no cycle flag.
Verify: A -weight loop leaves distances unchanged after one lap, so dist[u]+w < dist[v] is never strictly satisfied. Bellman-Ford flags strictly negative cycles only — the strict < is exactly what keeps the fence-case silent. ✓
Ex 9 — Cell I: real-world word problem
Forecast: which is better, (rate ) or (rate )? The bigger product = the more negative summed toll.
- Model. Turn "multiply rates" into "add tolls" via . Why this step? Bellman-Ford adds weights; logarithms turn products into sums, so a profitable path = a smallest (most negative) sum. A negative cycle here would mean arbitrage (free money looping trades).
- Init.
dist = [0, ∞, ∞]for . - Relax. :
dist[B] = -ln 2 ≈ -0.6931. :-ln2 - ln3 = -ln6 ≈ -1.7918. :-ln5 ≈ -1.6094. Since , keepdist[C] = -ln6. - Extra pass. No cycle (edges only go forward) → no arbitrage.
Answer: best route with summed toll , i.e. rate (beats direct ).
Verify: and , so the two-hop trade genuinely yields more currency. The chosen path corresponds to the smallest weight, exactly what shortest-path minimises. ✓ (Arbitrage detection via negative cycles is a classic Bellman-Ford application — see Shortest Path Problem.)
Ex 10 — Cell J: exam twist "which pass first settles ?"
Forecast: with the worst possible order, information crawls one edge per pass — so guess a number near .
- Pass 1. Only can fire (all others start from ):
dist[1]=1. Reach = 1 hop. - Pass 2. fires:
dist[2]=2. Reach = 2 hops. - Pass 3.
dist[3]=3. Pass 4.dist[4]=4. Why this step? With reversed order, each pass pushes the "frontier" exactly one edge forward, so vertex at depth settles on pass .
Answer: dist[4]=4 first correct on pass 4 (, the worst case). Fewer passes would leave it .
Verify: Longest shortest-path here has edges . The reversed order is the pathological one that actually needs all passes — proving the bound is tight, not loose. ✓
Recall Which cell trips you up?
Ex 4 vs Ex 5 — both contain a negative cycle. Why does only one get flagged? Only Ex 4's cycle is reachable from the source; Ex 5's cycle sits in an unreachable component so its vertices stay and its edges are never relaxed.
Ex 4 vs Ex 8 — both have a cycle. Why does only Ex 4 flag?
Ex 4's cycle sums to (strictly negative → relax fires forever); Ex 8's sums to (the strict < never triggers).
Recall checks
Connections
- Dijkstra's Algorithm — would fail Ex 2 by finalizing the wrong
dist[2] - Dynamic Programming — every pass = advancing (edges used) in the DP
- Floyd-Warshall — the all-pairs cousin, also survives negatives
- Shortest Path Problem · Negative Weight Cycles · Graph Relaxation · SPFA