Shortest Paths: Dijkstra & Bellman-Ford

This deck builds single-source shortest paths from one shared primitive, edge relaxation. It traces Dijkstra's algorithm by hand with a priority queue and explains why its greedy choice is safe only for non-negative weights, then covers Bellman-Ford's V-1 rounds of relaxation and its negative-cycle detection. It targets the traps of trusting Dijkstra with a negative edge, relaxing in the wrong direction, misjudging why V-1 rounds are needed, and reviving a vertex that has already been settled.

Subject: CS3000 Algorithms · 129 slides · symbolic lesson

Open the interactive version of this deck · Homework for this lesson

What this lesson covers

The lesson, slide by slide

1. Shortest Paths: Dijkstra & Bellman-Ford

Title

CS3000 Algorithms

Finding the cheapest way from one vertex to every other vertex.

2. What you will be able to do

Objectives

By the end of this lesson you can:

1. Explain what edge relaxation is and use it as the shared building block of both algorithms below.

2. Trace Dijkstra's algorithm on a small graph using a priority queue, and explain why its greedy choice is safe only when every edge weight is non-negative.

3. Trace Bellman-Ford's algorithm, explain why relaxing every edge V-1 times is exactly enough, and use one extra round to detect a negative-weight cycle.

4. State the running time of each algorithm and choose the right one for a given graph.

3. What survived from Topological Sort & Strongly Connected Components?

Warm-up

Discussion prompt

Before we open Shortest Paths: Dijkstra & Bellman-Ford: without looking back, what was the main idea of Topological Sort & Strongly Connected Components, and what could you do by the end of it that you could not do before?

Hint: One sentence for the idea, one for the skill. If the second one is blank, that is the part to revisit.

Answer:

Two ways to linearize a DAG (DFS finish-time order and Kahn's in-degree removal), how strongly connected components are found with Kosaraju's two-pass reverse-graph idea, and why the condensation of any graph's SCCs is always a DAG. Targets trying to sort a cyclic graph, the false belief that a topological order is unique, mixing up a directed SCC with an undirected connected component, and forgetting to reverse the graph in Kosaraju's algorithm.

4. Toolkit check-in: name them before you look

Concept

Before any new material: cover the screen.

You have named 14 reusable moves so far. Say as many as you can out loud, by number, from memory.

Do not advance until you have actually tried. Getting four of eight is information; skipping the exercise is not.

Here they are. Score yourself.

Today adds one move to this list. Everything else you will need is already above.

The question that starts every proof from here on is not how do I begin. It is which of these applies here?

5. Break it if you can: Toolkit check-in: name them before you look

Counterexample

Discussion prompt

You have named 14 reusable moves so far. Say as many as you can out loud, by number, from memory.

That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.

Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.

Answer:

Do not advance until you have actually tried. Getting four of eight is information; skipping the exercise is not.

6. The Shortest-Path Problem

Section

Section 1

7. Graphs, vertices, and weighted edges

Concept

A graph is a set of vertices (the dots, also called nodes) connected by edges (the links between them). In this lesson every edge points in one direction, from one vertex to another.

weight — A number attached to an edge, representing its cost: distance, time, price, or anything else you want to minimize along a route.

A path is a sequence of edges chained head to tail. The cost of a path is just the sum of the weights of the edges you used to walk it.

8. By analogy: Graphs, vertices, and weighted edges

Analogy

Discussion prompt

Explain Graphs, vertices, and weighted edges by analogy to something with no CS3000 Algorithms in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.

Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.

Answer:

A graph is a set of vertices (the dots, also called nodes) connected by edges (the links between them). In this lesson every edge points in one direction, from one vertex to another.

9. What single-source shortest path means

Concept

The single-source shortest-path problem: pick one starting vertex, the source, and find the cheapest possible path from it to every other vertex in the graph, all at once.

The output is a distance estimate for every vertex, usually called dist. dist of a vertex is the total weight of the cheapest path found so far from the source to it.

Both algorithms in this lesson build and improve this same dist array until it is guaranteed correct.

10. Teach it back: What single-source shortest path means

Explain it

Discussion prompt

Explain What single-source shortest path means to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.

Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.

Answer:

The single-source shortest-path problem: pick one starting vertex, the source, and find the cheapest possible path from it to every other vertex in the graph, all at once.

11. Why shortest paths decompose

Picture it

Animation

Shows: Why shortest paths decompose — a rendered Manim animation.

Rendered with Manim.

Takeaway: The property every shortest-path algorithm silently relies on.

12. A map where roads have costs, not just directions

Intuition

Picture a road map. Towns are vertices, roads are edges, and each road's toll or drive time is its weight. 'Shortest path' does not mean fewest roads — it means the cheapest total toll.

A route with three cheap roads can beat a route with one expensive one. That is exactly why we track running totals, dist, instead of counting hops.

13. Picture it first: Meet the example graph

Picture it

Figure (svg): A directed weighted graph with vertex S as the source, edges S to C weight 2, S to B weight 4, C to B weight 1, C to D weight 8, C to E weight 10, B to D weight 5, and D to E weight 2

Discussion prompt

Read the picture before the words. What is this showing, and what is the one thing it is built to make obvious? Commit to an answer, then read on.

Hint: Name the parts, then say what changes between them — and if nothing changes, say what is being held still.

Answer:

Both algorithms in this lesson will be traced on the same small graph, so you can compare their behavior directly. Source vertex S, plus four more vertices: B, C, D, E.

14. Meet the example graph

Concept

Both algorithms in this lesson will be traced on the same small graph, so you can compare their behavior directly. Source vertex S, plus four more vertices: B, C, D, E.

Figure (svg): A directed weighted graph with vertex S as the source, edges S to C weight 2, S to B weight 4, C to B weight 1, C to D weight 8, C to E weight 10, B to D weight 5, and D to E weight 2

Every weight here is non-negative, which matters a great deal, as you'll soon see. We'll call this graph G1 and reuse it for both algorithms.

15. Edge relaxation: the shared building block

Concept

Both Dijkstra and Bellman-Ford are built entirely out of one repeated move: relaxing an edge.

relax an edge — Given an edge from u to v with some weight, check whether going from the source to u, then across this edge, beats the best known way to reach v. If it does, update v's distance estimate and remember u as the way you got there.

The rule is a single comparison:

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

Notice the direction: you always add to the KNOWN side, dist[u], and compare against the side you might improve, dist[v]. Getting that backwards is a real and common bug — more on that shortly.

16. Take the definitions apart: weight vs relax an edge

Definition probe

Sort into buckets

Every line below is part of the definition of weight or of relax an edge — one or the other, never both. Put each where it belongs.

weight
A number attached to an edge, representing its cost; distance, time, price, or anything else you want to minimize along a route.
relax an edge
Given an edge from u to v with some weight, check whether going from the source to u, then across this edge, beats the best known way to reach v.; If it does, update v's distance estimate and remember u as the way you got there.
b1
A number attached to an edge, representing its cost: distance, time, price, or anything else you want to minimize along a route.
b2
Given an edge from u to v with some weight, check whether going from the source to u, then across this edge, beats the best known way to reach v. If it does, update v's distance estimate and remember u as the way you got there.

17. A rumor of a shorter route

Intuition

Think of dist[v] as the best rumor you've heard so far about how cheaply you can reach v. Relaxing an edge into v is hearing one more rumor: 'you can reach u for this much, and then it's one more hop to v.'

If the new rumor is cheaper than the best one you're holding, you update. If it's not, you ignore it and keep what you had. Nothing more mysterious than that.

18. Picture it first: Relax a single edge

Picture it

Figure (svg): Vertex u with distance 2 connected by an edge of weight 4 to vertex v with current distance 9

Discussion prompt

Read the picture before the words. What is this showing, and what is the one thing it is built to make obvious? Commit to an answer, then read on.

Hint: Name the parts, then say what changes between them — and if nothing changes, say what is being held still.

Answer:

Suppose we already know dist[u] = 2. There is an edge from u to v with weight 4, and the current best estimate is dist[v] = 9.

19. Relax a single edge

Worked example

Suppose we already know dist[u] = 2. There is an edge from u to v with weight 4, and the current best estimate is dist[v] = 9.

Figure (svg): Vertex u with distance 2 connected by an edge of weight 4 to vertex v with current distance 9

Compute the candidate distance through u

Why: Add u's known distance to the weight of the edge — this is the cost of the route that goes to u first, then hops to v.

\[ dist[u] + w(u,v) = 2 + 4 = 6 \]

Compare the candidate to the current estimate

Why: The candidate route costs 6, which is less than the 9 we currently believe. This route is a genuine improvement.

\[ 6 < 9 \]

Update dist[v] and prev[v]

Why: Since the comparison succeeded, replace v's estimate with the cheaper number, and record u as the vertex we'd arrive from.

\[ dist[v] \leftarrow 6, \quad prev[v] \leftarrow u \]

Verify the update really is an improvement

Why: 6 is less than the old value of 9, and it was computed honestly as dist[u] plus the real edge weight, so the update is legitimate. If a later relaxation finds something even cheaper, it will replace 6 the same way.

\[ 6 < 9\ \checkmark \]

20. Decode the notation: Relax a single edge

Notation

Annotate

From Relax a single edge — read this one piece at a time. What is each part doing?

On: \( dist[u] + w(u,v) = 2 + 4 = 6 \)

  • Add u's known distance to the weight of the edge — this is the cost of the route that goes to u first, then hops to v.
  • The candidate route costs 6, which is less than the 9 we currently believe. This route is a genuine improvement.
  • Since the comparison succeeded, replace v's estimate with the cheaper number, and record u as the vertex we'd arrive from.

21. Something is wrong here: relaxing in the wrong direction

Anomaly

Predict first

A student writes this, and it looks reasonable:

A student mixes up which side of the comparison is the 'known' side and which is the side being improved.

It is wrong. Say what breaks — and say it before you turn the page.

Correct: This student writes the comparison as if v's distance plus the weight should beat u's distance — the roles are swapped.

Always add the weight to the vertex whose distance is already trusted, and compare against the vertex you might be improving.

Why: This student writes the comparison as if v's distance plus the weight should beat u's distance — the roles are swapped.

22. Trap: relaxing in the wrong direction

Trap

The trap

A student mixes up which side of the comparison is the 'known' side and which is the side being improved.

\[ dist[u]=2,\ \ dist[v]=9,\ \ w(u,v)=4 \]

Check the backwards condition

Why: This student writes the comparison as if v's distance plus the weight should beat u's distance — the roles are swapped.

\[ \text{if } dist[v] + w(u,v) < dist[u]:\ \ 9 + 4 = 13 < 2 \ ?\ \ \text{false} \]

The update never fires

Why: Because the backwards condition is false, dist[v] stays at 9 forever, even though a cheaper route through u genuinely exists. The bug doesn't crash — it just silently produces a worse answer.

\[ dist[v] \text{ stuck at } 9 \quad (\text{should be } 6) \]

The fix

Always add the weight to the vertex whose distance is already trusted, and compare against the vertex you might be improving.

\[ dist[u]=2,\ \ dist[v]=9,\ \ w(u,v)=4 \]

Check the correct condition

Why: u is the known side, so its distance plus the edge weight is the candidate for v.

\[ \text{if } dist[u] + w(u,v) < dist[v]:\ \ 2 + 4 = 6 < 9 \ ?\ \ \text{true} \]

The update fires correctly

Why: dist[v] becomes 6, matching the real cheapest known route. A quick way to remember it: the edge runs FROM u TO v, and the arithmetic follows the arrow the same way.

\[ dist[v] \leftarrow 6\ \checkmark \]

23. Something is wrong here: starting distances at zero instead of infinity

Anomaly

Predict first

A student writes this, and it looks reasonable:

A student initializes every vertex's distance to 0 'to be safe', instead of only the source.

It is wrong. Say what breaks — and say it before you turn the page.

Correct: The candidate distance through S is 0 plus 2 equals 2, but C's current estimate is already 0, which looks smaller.

Only the source starts at 0. Every other vertex starts at infinity, meaning 'no route found yet'.

Why: The candidate distance through S is 0 plus 2 equals 2, but C's current estimate is already 0, which looks smaller. The comparison fails and NOTHING updates.

24. Trap: starting distances at zero instead of infinity

Trap

The trap

A student initializes every vertex's distance to 0 'to be safe', instead of only the source.

\[ dist[S]=0,\ dist[B]=0,\ dist[C]=0,\ dist[D]=0,\ dist[E]=0 \]

Try to relax the edge from S to C, weight 2

Why: The candidate distance through S is 0 plus 2 equals 2, but C's current estimate is already 0, which looks smaller. The comparison fails and NOTHING updates.

\[ dist[S] + w(S,C) = 0 + 2 = 2 \ \not< \ 0 = dist[C] \]

Every real relaxation gets blocked

Why: Because every non-source vertex already 'looks' reachable for free, no honest relaxation ever beats 0, and every dist value freezes at the wrong answer, 0.

The fix

Only the source starts at 0. Every other vertex starts at infinity, meaning 'no route found yet'.

\[ dist[S]=0,\ dist[B]=\infty,\ dist[C]=\infty,\ dist[D]=\infty,\ dist[E]=\infty \]

Relax the edge from S to C, weight 2

Why: Any finite number beats infinity, so the very first honest relaxation into an unreached vertex is guaranteed to succeed.

\[ dist[S] + w(S,C) = 0 + 2 = 2 \ < \ \infty\ \checkmark \]

Infinity means 'unknown', not 'free'

Why: Initializing to infinity guarantees that the first real path discovered always counts as an improvement, which is exactly what should happen.

25. Unreachable vertices stay at infinity

Concept

Not every vertex has to be reachable from the source. If no chain of edges leads from the source to some vertex, no relaxation will ever fire for it.

That vertex's dist value simply stays at infinity forever, in both algorithms. Infinity there does not mean an error — it correctly reports 'no path exists'.

\[ dist[v] = \infty \ \text{at the end} \ \Rightarrow\ v \text{ is unreachable from the source} \]

26. The relaxation recipe

Pattern

1. Initialize the source to 0, everyone else to infinity

Why: The source needs no path to reach itself; everyone else starts as 'unknown' so the first real route always wins.

2. For an edge from u to v, add dist[u] to the weight

Why: Always build the candidate from the KNOWN side, u, across the edge, toward the side you might improve, v.

3. Compare the candidate to dist[v]; update only if it's smaller

Why: This single comparison, repeated over and over on different edges, is the entire engine behind both algorithms in this lesson.

4. When you update dist[v], also update prev[v]

Why: Recording the vertex you arrived from lets you reconstruct the actual cheapest path later, not just its total cost.

27. Check yourself: does this relaxation fire?

Check

There is an edge from vertex p to vertex q with weight 3. Currently dist[p] = 5 and dist[q] = 6.

Check your understanding

What happens when this edge is relaxed?

  • A. dist[q] updates to 8
  • B. dist[q] updates to 6 (no change, since 3 is less than 6)
  • C. dist[p] updates to 8
  • D. dist[q] stays 6, since the candidate 8 is not smaller than 6 (correct)

Answer: D

Why: The candidate distance through p is dist[p] + weight = 5 + 3 = 8. Since 8 is not less than the current dist[q] = 6, the relaxation does not fire and dist[q] correctly stays at 6.

Why A tempts people
This computes the candidate correctly as 8 but forgets to compare it against dist[q] = 6 before updating; 8 is worse than 6, so no update should happen.
Why B tempts people
This compares the raw edge weight (3) to dist[q] (6) instead of comparing the full candidate distance (dist[p] + weight = 8) to dist[q].
Why C tempts people
This updates the wrong vertex. The edge runs from p to q, so only q's distance is ever a candidate for improvement here, never p's.

28. Dijkstra's Algorithm

Section

Section 2

29. Dijkstra's big idea: settle the closest vertex first

Concept

Dijkstra's algorithm repeatedly does one thing: find the unfinished vertex with the smallest current distance estimate, declare its distance final, and relax every edge leaving it.

settled — A vertex whose dist value has been declared final and will never be changed again for the rest of the algorithm.

This repeats — always picking the closest unsettled vertex next — until every vertex is settled.

30. Dijkstra's algorithm in pseudocode

Concept

BFS with a priority queue instead of a plain queue. Take the closest unsettled vertex, settle it forever, and relax its edges.

DIJKSTRA(G, s)
  for each u in V
    dist[u] = INFINITY
  dist[s] = 0
  Q = priority queue of all vertices, keyed by dist
  while Q is not empty
    u = Extract-Min(Q)
    for each v in Adj[u]
      if dist[u] + w(u, v) < dist[v]
        dist[v] = dist[u] + w(u, v)
        parent[v] = u
        Decrease-Key(Q, v)

Line 7 is the greedy choice and the load-bearing one. It claims the nearest unsettled vertex already has its final distance. That claim needs every weight to be non-negative — a negative edge could otherwise shorten a path after it was settled.

31. Reading DIJKSTRA line by line

Notation

Every line of DIJKSTRA says one thing. Read the line, then read what it does — not the other way round.

Annotate

  • The closest unsettled vertex. Extracting the minimum is what makes this greedy, and it is the line the correctness proof is about.
  • Once extracted, a vertex is settled and never revisited. That is safe ONLY because no edge can have negative weight.
  • The relaxation test: is going through u better than what v already had?
  • The distance can only fall, never rise. Every write to dist is an improvement over the previous value.
  • The parent pointer changes with the distance, so the recorded path always matches the recorded length.
  • Tell the queue that v got cheaper. Counting these operations is where the log factor in the running time comes from.

32. Step DIJKSTRA yourself

Invariant

Every settled vertex has its true shortest distance, permanently. Everything still in the queue holds the best distance found so far, which can still improve.

Step through it

Before each extraction, name which vertex you expect to be settled next.

  1. Line 4: the source, at distance 0
  2. Line 7: settle s
  3. Line 10: relax the edge of weight 4
  4. Line 10: and the edge of weight 9
  5. Line 7: 4 is smaller than 9, so a settles next
  6. Line 9: 4 plus 3 beats 9: b improves
  7. Line 10: c is reached at 6
  8. Line 7: 6 is the smallest left, so c settles
  9. Line 9: d reached at 8 through c
  10. Line 7: b settles at 7, and nothing improves d

33. Settle the nearest, then relax outward

Picture it

Animation

Shows: DIJKSTRA executing: the current line of pseudocode is highlighted while the data it touches changes.

Rendered with Manim.

Takeaway: Settle the nearest unsettled vertex and relax its edges — correct only because no edge weight is negative.

34. Send the next courier to the nearest town

Intuition

Imagine dispatching couriers from a warehouse. You always send the next courier to whichever known town is currently cheapest to reach. Once a courier arrives, that town's delivery cost is locked in.

From that town, you discover new, possibly cheaper routes to its neighbors, and add those to your list of towns to consider next.

35. Settled vs. unsettled, and the priority queue

Concept

Dijkstra keeps two groups: settled vertices, whose distance is final, and unsettled vertices, whose distance is still just an estimate.

priority queue — A data structure that always hands you the item with the smallest key, efficiently. Here, the key is a vertex's current distance estimate.

Each step: pop the unsettled vertex with the smallest estimate from the priority queue, mark it settled, and relax its outgoing edges — which may push better estimates for its neighbors back into the queue.

36. The heap is where the running time lives

Picture it

Animation

Shows: The heap is where the running time lives — a rendered Manim animation.

Rendered with Manim.

Takeaway: The algorithm is unchanged; only the data structure moves the bound.

37. dist and prev: what both algorithms track

Concept

Both Dijkstra and Bellman-Ford maintain the same two pieces of bookkeeping for every vertex.

prev — For a vertex v, prev[v] stores the vertex you arrive from on the cheapest known path to v. Following prev pointers backward from any vertex to the source reconstructs the actual path, not just its cost.

dist answers 'how much does it cost'; prev answers 'which way do I actually go'. You need both to fully solve the problem.

38. Decision point: why is settling the closest vertex safe?

Intuition

What move should we make next?

Dijkstra settles the unsettled vertex with the smallest tentative distance and never revisits it.

\[ \text{claim: when } u \text{ is settled, } dist[u] = \delta(s, u) \]

A cheaper route to u would have to arrive through some vertex that is still unsettled.

This is a for-all claim about every settle. Which move, and what exactly would you assume goes wrong?

_Look at your toolkit. Say a move number out loud before this slide advances._ A wrong guess is useful. A silent guess is not.

39. Why the greedy choice is safe with non-negative weights

Concept

Dijkstra's whole method rests on one guarantee: once you settle the closest unsettled vertex, its distance can never improve later. Why is that guaranteed?

Every unsettled vertex's current estimate is already at least as large as the one you're about to settle, since you always pick the smallest. Any future path to the settled vertex would have to pass through some unsettled vertex first.

\[ \text{any future path} = \text{through some unsettled } x, \quad dist[x] \ge dist[\text{chosen vertex}] \]

Because every edge weight is non-negative, continuing from x can only add more cost, never subtract it. So no future route can ever beat the one you already locked in.

\[ dist[x] + w(x, \ldots) \ge dist[x] \ge dist[\text{chosen vertex}] \]

40. The First-Failure skeleton

Concept

Every proof of this kind has the same five or six moves in the same order. The order is not something you rediscover each time.

It is on the right. It will stay on the right through the worked examples that follow.

Why this matters: the structure is now handled. You are not spending working memory on what comes next — you are spending all of it on the one hard step.

Step 2 is what makes the proof finite. Reasoning about somewhere it fails gives you nothing; reasoning about the first failure hands you a fully-correct prefix to argue from.

41. Complete the line: The new move, named

Fill the middle

Fill in the blanks

From The new move, named — finish the line. Write what belongs on the right of the equals sign before you look.

dist[y] = \delta(s, y) \le \delta(s, u) \le dist[u]

Why: Producing the right-hand side unprompted is the difference between recognising this line and being able to use it. Suppose some vertex is settled with a wrong distance.

42. The new move, named

Concept

The move: #15 (Cut at the first failure).

Assume the claim fails and take the FIRST failure

Why: Suppose some vertex is settled with a wrong distance. Let u be the first such vertex, in settle order. Every vertex settled before u is therefore correct — and that prefix of correctness is the thing you get to use.

Look at the true shortest path to u

Why: Walk it from s toward u and find the first vertex y on it that is not yet settled. The vertex x just before y is settled, hence correct, hence the edge from x to y was already relaxed.

\[ dist[y] = \delta(s, y) \le \delta(s, u) \le dist[u] \]

Show the step could not have happened

Why: So y had a tentative distance no larger than u's, and Dijkstra would have settled y instead of u. The first failure could not have occurred, so there is no failure at all.

Non-negative weights are what make the middle inequality true. Allow one negative edge and that line is false, which is precisely why Dijkstra breaks there. Note that this is #8 (Take the extreme one) with the ordering supplied by the algorithm.

43. Say it in words: The new move, named

Translation

\( dist[y] = \delta(s, y) \le \delta(s, u) \le dist[u] \)

Draw it

Translate both ways. First write the expression above as a sentence with no symbols in it at all. Then cover it, and write your sentence back as notation. If the two versions disagree, the disagreement is the thing to fix.

44. No shortcut can hide through a farther vertex

Intuition

Picture every unsettled vertex as sitting at or beyond the distance of the one you're about to settle. Any path that detours through one of them can only add distance from there — like a toll booth that never gives refunds.

That 'never gives refunds' property is exactly what a negative weight would violate. Keep that thought — it's the whole reason for the trap coming up soon.

45. What has to happen first: Dijkstra trace: initializing and the first two settles

Ranking

Put in order

Put the moves of Dijkstra trace: initializing and the first two settles into the order they have to happen.

  1. Settle S and relax its edges
  2. Settle C and relax its edges
  3. Check the running tally after two settles

Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. S has the smallest distance, 0, so it settles first.

46. Dijkstra trace: initializing and the first two settles

Worked example

Run Dijkstra on graph G1 from source S. Recall the edges: S to C weight 2, S to B weight 4, C to B weight 1, C to D weight 8, C to E weight 10, B to D weight 5, D to E weight 2.

Initialize

Why: The source starts at 0; everyone else starts at infinity, unsettled.

stepsettleddist[S]dist[B]dist[C]dist[D]dist[E]
0-0∞∞∞∞

Settle S and relax its edges

Why: S has the smallest distance, 0, so it settles first. Relaxing S to C (weight 2) and S to B (weight 4) gives both their first real estimates.

stepsettleddist[S]dist[B]dist[C]dist[D]dist[E]
1S042∞∞

Settle C and relax its edges

Why: Among unsettled vertices, C has the smallest estimate, 2, so it settles next. Relaxing C to B improves B from 4 to 3; relaxing C to D and C to E gives them their first estimates.

stepsettleddist[S]dist[B]dist[C]dist[D]dist[E]
2S, C0321012

Check the running tally after two settles

Why: So far: S is settled at 0, C is settled at 2. B, D, and E are only estimates (3, 10, 12) and could still improve, since they are not yet settled.

47. Dijkstra trace: finishing up

Worked example

Continuing from where we left off: S and C are settled. The priority queue currently holds B at 3, D at 10, and E at 12 (plus a stale leftover entry for B at 4, from before C improved it — more on that soon).

Settle B and relax its edges

Why: B has the smallest unsettled estimate, 3. Relaxing B to D (weight 5) gives candidate 3 + 5 = 8, which beats the current D estimate of 10.

stepsettleddist[S]dist[B]dist[C]dist[D]dist[E]
3S, C, B032812

Settle D and relax its edges

Why: D now has the smallest unsettled estimate, 8. Relaxing D to E (weight 2) gives candidate 8 + 2 = 10, which beats the current E estimate of 12.

stepsettleddist[S]dist[B]dist[C]dist[D]dist[E]
4S, C, B, D032810

Settle E

Why: E is the only unsettled vertex left, at 10. No outgoing edges remain to relax. Every vertex is now settled.

stepsettleddist[S]dist[B]dist[C]dist[D]dist[E]
5S, C, B, D, E032810

Verify every vertex is settled and the distances are final

Why: All five vertices appear in the settled column and no priority-queue entries remain that could still improve them. Final distances: S=0, C=2, B=3, D=8, E=10.

\[ dist[S]=0,\ dist[C]=2,\ dist[B]=3,\ dist[D]=8,\ dist[E]=10 \]

48. Prim and Dijkstra differ in one word

Picture it

Animation

Shows: Prim and Dijkstra differ in one word — a rendered Manim animation.

Rendered with Manim.

Takeaway: Nearly the same code, and a completely different answer.

49. Plan first: Reconstructing the shortest path with prev pointers

Step zero

Discussion prompt

Reconstructing the shortest path with prev pointers — before any calculation: what is the plan? Name the moves in order, in plain English, without doing the arithmetic.

Hint: It starts with: Start at the destination and follow prev backward

Answer:

  1. Start at the destination and follow prev backward
  2. Keep following prev pointers
  3. Reach the source and reverse the chain
  4. Verify the reconstructed path costs exactly 10

50. Reconstructing the shortest path with prev pointers

Worked example

The trace above also recorded a prev pointer every time it updated a distance. Use them to reconstruct the actual cheapest path from S to E, not just its cost.

vertexprev
CS
BC
DB
ED

Start at the destination and follow prev backward

Why: prev[E] is D, since E's final estimate of 10 came from relaxing the edge D to E.

\[ E \leftarrow D \]

Keep following prev pointers

Why: prev[D] is B, and prev[B] is C, chaining the path backward one hop at a time.

\[ E \leftarrow D \leftarrow B \leftarrow C \]

Reach the source and reverse the chain

Why: prev[C] is S, the source, so the chain stops there. Reversing it gives the path in forward order.

\[ S \rightarrow C \rightarrow B \rightarrow D \rightarrow E \]

Verify the reconstructed path costs exactly 10

Why: Add up the edge weights along this exact path: S to C is 2, C to B is 1, B to D is 5, D to E is 2. The total matches dist[E].

\[ 2 + 1 + 5 + 2 = 10\ \checkmark \]

51. What feels wrong about a negative edge here?

Intuition

What feels wrong about this?

Dijkstra settles a vertex and promises never to look at it again.

\[ \text{settled} \;\Rightarrow\; \text{final} \]

Now add an edge of weight minus 5 somewhere further out in the graph.

_Plain English only. No notation, no algebra. Just say what bothers you._

The feeling: a promise made early can be broken by something discovered later. Nothing stops a bargain from turning up after you already stopped looking.

That feeling is the proof. It is not a substitute for the proof — it is the thing the proof writes down.

Look back at the proof: the step that fails is the inequality claiming a partial path is never longer than the whole path. With a negative edge, going further can cost less, and that single line collapses.

52. Trap: trusting Dijkstra with a negative edge weight

Trap

The trap

A student runs Dijkstra as usual on a graph with a negative edge, and trusts the result without question.

Figure (svg): A directed graph with source S, edge S to A weight 4, edge S to B weight 1, and edge A to B weight negative 10

Settle S, then settle B before A

Why: Relaxing from S gives dist[A]=4 and dist[B]=1. Since 1 is smaller than 4, Dijkstra settles B first and locks its distance in as final.

\[ dist[B] = 1 \ (\text{settled, locked in}) \]

Settle A and relax A to B anyway — too late

Why: Relaxing A to B gives candidate 4 + (-10) = -6, far cheaper than 1. But B is already settled, so a correct Dijkstra implementation never revisits it. The final answer stays wrong.

\[ dist[B] \text{ reported as } 1 \quad (\text{true shortest is } -6) \]

The fix

The real cheapest path is S to A to B, costing 4 + (-10) = -6, which beats the direct edge's cost of 1. Dijkstra can never discover this, because it never reopens a settled vertex.

\[ \min(1,\ 4 + (-10)) = \min(1, -6) = -6 \]

Recognize why the greedy proof breaks

Why: The safety argument relied on 'continuing past an unsettled vertex can only add cost'. A negative edge violates that directly: continuing past A actually subtracted 10 from the running total.

\[ dist[A] + w(A,B) = 4 + (-10) = -6 < dist[A] \]

Use Bellman-Ford instead

Why: Bellman-Ford never assumes a vertex is 'done' until all V-1 rounds finish, so it correctly finds -6. We'll trace this exact graph with Bellman-Ford later in this lesson.

53. Break it on purpose: trusting Dijkstra with a negative edge weight

Break the constraint

Discussion prompt

The rule this trap just fixed:

The safety argument relied on 'continuing past an unsettled vertex can only add cost'. A negative edge violates that directly: continuing past A actually subtracted 10 from the running total.

Now break it on purpose. Build a case that violates it and follow the consequences until something visibly fails. Where does the failure first show up — and would you have noticed it if you had not been looking?

Hint: The dangerous rules are the ones whose violation still produces an answer. If yours fails loudly, try to find one that fails quietly.

Answer:

Relaxing from S gives dist[A]=4 and dist[B]=1. Since 1 is smaller than 4, Dijkstra settles B first and locks its distance in as final.

54. Something is wrong here: reviving a vertex Dijkstra already settled

Anomaly

Predict first

A student writes this, and it looks reasonable:

Recall the trace on G1: B first got a tentative distance of 4 (from relaxing S to B), then improved to 3 (from relaxing C to B). Both entries, 4 and 3, ended up sitting in the priority queue at the same time.

It is wrong. Say what breaks — and say it before you turn the page.

Correct: A buggy implementation forgets to check whether a popped vertex is already settled.

A correct implementation checks, immediately after popping a vertex from the priority queue, whether it is already settled — and if so, discards the entry and moves on.

Why: A buggy implementation forgets to check whether a popped vertex is already settled. After D is settled at 8, the leftover entry {B, 4} is popped next, since 4 is less than E's 10 — and the buggy code treats this as settling B all over again.

55. Trap: reviving a vertex Dijkstra already settled

Trap

The trap

Recall the trace on G1: B first got a tentative distance of 4 (from relaxing S to B), then improved to 3 (from relaxing C to B). Both entries, 4 and 3, ended up sitting in the priority queue at the same time.

\[ \text{queue holds two entries for B: } 4 \text{ and } 3 \]

Pop the stale entry and 're-settle' B

Why: A buggy implementation forgets to check whether a popped vertex is already settled. After D is settled at 8, the leftover entry {B, 4} is popped next, since 4 is less than E's 10 — and the buggy code treats this as settling B all over again.

\[ dist[B] \text{ overwritten: } 3 \rightarrow 4 \quad (\text{wrong — B was already correctly settled at 3}) \]

The wrong distance and wrong prev pointer stick

Why: Because the code re-processed a stale, worse entry, it silently corrupts both dist[B] and prev[B] after they were already correct.

The fix

A correct implementation checks, immediately after popping a vertex from the priority queue, whether it is already settled — and if so, discards the entry and moves on.

\[ \text{queue holds two entries for B: } 4 \text{ and } 3 \]

Pop the stale entry and discard it

Why: When {B, 4} is popped later, the algorithm sees B is already settled (with the correct value 3) and simply skips this leftover entry, doing no work.

\[ \text{B already settled at } 3 \Rightarrow \text{discard the stale entry} \]

Never touch a settled vertex again

Why: This 'settled means permanently done' rule is exactly what the safety argument for non-negative weights depends on. Skipping stale entries costs nothing but a discarded check.

56. Ties in the priority queue

Concept

What if two unsettled vertices have the exact same distance estimate? Either one may be settled first — the final dist values come out identical either way.

This is safe because of the same non-negative-weight argument from before: whichever of the tied vertices you settle first, its distance still cannot be improved later, since every other unsettled vertex's estimate is at least as large.

57. What rests on this: Ties in the priority queue

Socratic

Discussion prompt

What if two unsettled vertices have the exact same distance estimate? Either one may be settled first — the final dist values come out identical either way.

Suppose that were not true. What is the first thing in Shortest Paths: Dijkstra & Bellman-Ford that would stop working?

Hint: Follow it one step downstream. The answer is whatever was quietly relying on it.

58. Dijkstra's running time

Concept

With a binary heap as the priority queue, Dijkstra runs in:

\[ O\big((V+E)\log V\big) \]

V is the number of vertices, E is the number of edges. This is fast enough to be practical even on large road networks with millions of intersections.

59. Extract-min and decrease-key: counting the operations

Concept

Each vertex is settled exactly once, which means exactly V extract-min operations over the whole run — each one costing logarithmic time in a binary heap.

\[ V \text{ extract-min calls}, \quad O(\log V) \text{ each} \]

Every edge is relaxed at most once (when its tail is settled), and each successful relaxation can trigger one decrease-key or insert, also logarithmic time.

\[ E \text{ relaxations}, \quad O(\log V) \text{ each} \]

Adding these two contributions together gives the total:

\[ O(V \log V) + O(E \log V) = O\big((V+E)\log V\big) \]

60. The Dijkstra recipe

Pattern

1. Initialize dist[source]=0, everyone else infinity; all unsettled

Why: Standard relaxation setup, with a priority queue keyed on dist.

2. Repeatedly pop the smallest unsettled vertex from the queue

Why: If it's already settled (a stale entry), discard it and pop again.

3. Mark it settled and relax every outgoing edge

Why: This may improve neighbors' estimates and push new queue entries.

4. Stop when every vertex is settled

Why: Non-negative weights guarantee each settled distance is already final — the safety argument from earlier in this section.

61. Dijkstra on the very same graph

Picture it

Animation

Shows: Dijkstra on the very same graph — a rendered Manim animation.

Rendered with Manim.

Takeaway: Different parents from Prim: Dijkstra minimises distance FROM A, not edge weight.

62. Rule out three: Check yourself: why is settling safe?

Elimination

Eliminate the wrong options

Why is it safe to treat this vertex's distance as permanently final right now?

3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.

  • A. Because every edge weight is non-negative, so continuing through any other unsettled vertex can only add cost, never subtract it
  • B. Because the graph has no cycles
  • C. Because the priority queue is guaranteed to contain exactly V entries at all times
  • D. Because Dijkstra double-checks every settled vertex again at the very end

Survives elimination: A

Why: Every unsettled vertex already has an estimate at least as large as the one being settled. With non-negative weights, any path detouring through an unsettled vertex can only get more expensive from there, so no cheaper route to the settled vertex can ever appear later.

63. Check yourself: why is settling safe?

Check

Dijkstra just popped the unsettled vertex with the smallest current distance estimate and is about to mark it settled.

Check your understanding

Why is it safe to treat this vertex's distance as permanently final right now?

  • A. Because every edge weight is non-negative, so continuing through any other unsettled vertex can only add cost, never subtract it (correct)
  • B. Because the graph has no cycles
  • C. Because the priority queue is guaranteed to contain exactly V entries at all times
  • D. Because Dijkstra double-checks every settled vertex again at the very end

Answer: A

Why: Every unsettled vertex already has an estimate at least as large as the one being settled. With non-negative weights, any path detouring through an unsettled vertex can only get more expensive from there, so no cheaper route to the settled vertex can ever appear later.

Why B tempts people
Dijkstra works correctly on graphs containing cycles; cycle-freeness is not what makes the greedy choice safe.
Why C tempts people
The priority queue's size changes throughout the run (it can even hold stale duplicate entries, as seen in the earlier trap) — its size is irrelevant to correctness.
Why D tempts people
Dijkstra never revisits settled vertices at all, which is precisely why a negative edge can leave a wrong answer uncorrected, as shown in the negative-weight trap.

64. Answer it before you see the options: Check yourself: reading prev pointers

Prediction

Predict first

What is the shortest path from S to D, and what does dist[D] represent?

Answer it in your own words, now, with nothing to choose from. The options are on the next slide — and picking the right one off a list is an easier skill than producing it.

Correct: The path is S to C to D, and 9 is the total weight of that exact path

Why: Following prev backward from D gives D, then C (since prev[D]=C), then S (since prev[C]=S). Reversing that chain gives the forward path S to C to D, and dist[D]=9 is the total summed weight of every edge along that exact path.

65. Check yourself: reading prev pointers

Check

In a Dijkstra run from source S, you're given: prev[D] = C, prev[C] = S, and dist[D] = 9.

Check your understanding

What is the shortest path from S to D, and what does dist[D] represent?

  • A. The path is S to C to D, and 9 is the total weight of that exact path (correct)
  • B. The path is D to C to S, and 9 is the number of edges used
  • C. The path is S to D directly, and 9 is just one edge's weight
  • D. There isn't enough information to know the path, only its cost

Answer: A

Why: Following prev backward from D gives D, then C (since prev[D]=C), then S (since prev[C]=S). Reversing that chain gives the forward path S to C to D, and dist[D]=9 is the total summed weight of every edge along that exact path.

Why B tempts people
This reverses the direction of travel and misreads dist as an edge count rather than a total weight — dist sums real edge weights, not hops.
Why C tempts people
prev[D] = C tells us directly that the path arrives at D via C, not straight from S — there must be at least two edges on this path.
Why D tempts people
The prev pointers ARE exactly the information needed to reconstruct the path — that's their whole purpose, as shown in the reconstruction worked example.

66. The Bellman-Ford Algorithm

Section

Section 3

67. Why we need another algorithm

Concept

Dijkstra is fast, but the negative-weight trap showed its core safety argument depends on every edge weight being non-negative. We need a different algorithm for graphs where that isn't true.

Bellman-Ford trades some speed for generality: it correctly handles negative edge weights, and can even detect when a graph has no correct shortest-path answer at all.

68. Let the rumor spread through the whole network, patiently

Intuition

Instead of greedily trusting the closest vertex right away, Bellman-Ford just relaxes every edge in the graph, over and over, for a fixed number of rounds — patiently letting good news propagate outward from the source.

No vertex is ever declared 'done' early. Everyone's estimate stays open to improvement until the fixed number of rounds is complete.

69. Bellman-Ford's big idea: relax every edge, V-1 times

Concept

Bellman-Ford's algorithm, in full: initialize distances as usual, then relax every edge in the graph, one full pass. Repeat this full pass V-1 times in total, where V is the number of vertices.

\[ \text{repeat } (V-1) \text{ times: for every edge } (u,v),\ \text{relax it} \]

That's the entire algorithm. No priority queue, no notion of 'settled' — just brute, repeated relaxation of the whole edge list.

70. Bellman-Ford in pseudocode

Concept

No priority queue, no cleverness about order. Relax every edge, then do it again, and repeat one time fewer than there are vertices.

BELLMAN-FORD(G, s)
  for each u in V
    dist[u] = INFINITY
  dist[s] = 0
  repeat V - 1 times
    for each edge (u, v) in E
      if dist[u] + w(u, v) < dist[v]
        dist[v] = dist[u] + w(u, v)
        parent[v] = u
  for each edge (u, v) in E
    if dist[u] + w(u, v) < dist[v]
      report a negative-weight cycle

Lines 7 and 8 are the identical relaxation Dijkstra uses. The difference is the total absence of a settled set: because nothing is ever final until the end, a negative edge cannot invalidate an earlier decision.

71. Reading BELLMAN-FORD line by line

Notation

Every line of BELLMAN-FORD says one thing. Read the line, then read what it does — not the other way round.

Annotate

  • Why V minus one: a shortest path is simple, so it has at most V minus one edges, and each round guarantees one more edge of every path is correct.
  • Every edge, in any order. Bellman-Ford makes no claim about which vertex to look at next, which is exactly why it tolerates negative weights.
  • The same relaxation as Dijkstra, character for character. Only the surrounding control flow differs.
  • One extra round after the answer should be final. If anything still improves, no finite answer exists.
  • A negative cycle means you can loop forever getting cheaper, so 'shortest path' stops being a well-defined question.
  • V minus one rounds over E edges: the running time is V times E, the price paid for handling negative weights.

72. Step BELLMAN-FORD yourself

Invariant

After round k, every vertex reachable by a shortest path of at most k edges holds its true distance. Round by round the correct answers spread one edge further out.

Step through it

After each round, say which vertices you can now be sure about.

  1. Line 4: only the source is known
  2. Line 8: round 1: paths of one edge
  3. Line 8: still round 1, in whatever order edges came
  4. Line 7: round 2: going via b beats the direct edge
  5. Line 8: so c improves too
  6. Line 8: round 3 reaches d
  7. Line 7: and a shorter route to d appears
  8. Line 11: the extra round improves nothing
  9. Line 12: so there is no negative cycle

73. Each round pushes the truth one edge further

Picture it

Animation

Shows: BELLMAN-FORD executing: the current line of pseudocode is highlighted while the data it touches changes.

Rendered with Manim.

Takeaway: Relax every edge V minus one times; one extra round that still improves anything proves a negative cycle.

74. Where does each piece belong: Shortest Paths: Dijkstra & Bellman-Ford

Sorting

Sort into buckets

These are the pieces of Shortest Paths: Dijkstra & Bellman-Ford, out of order. Put each one back under the part of the lesson it belongs to.

The Shortest-Path Problem
Graphs, vertices, and weighted edges; What single-source shortest path means; A map where roads have costs, not just directions
Dijkstra's Algorithm
Dijkstra's big idea: settle the closest vertex first; Send the next courier to the nearest town; Settled vs. unsettled, and the priority queue
The Bellman-Ford Algorithm
Why we need another algorithm; Let the rumor spread through the whole network, patiently; Bellman-Ford's big idea: relax every edge, V-1 times
s1
The Shortest-Path Problem is where Shortest Paths: Dijkstra & Bellman-Ford puts Graphs, vertices, and weighted edges, What single-source shortest path means, A map where roads have costs, not just directions. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.
s2
Dijkstra's Algorithm is where Shortest Paths: Dijkstra & Bellman-Ford puts Dijkstra's big idea: settle the closest vertex first, Send the next courier to the nearest town, Settled vs. unsettled, and the priority queue. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.
s3
The Bellman-Ford Algorithm is where Shortest Paths: Dijkstra & Bellman-Ford puts Why we need another algorithm, Let the rumor spread through the whole network, patiently, Bellman-Ford's big idea: relax every edge, V-1 times. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.

75. What a simple path is, and why it matters

Concept

simple path — A path that never repeats a vertex. Since it can visit at most V distinct vertices, a simple path has at most V-1 edges.

\[ \text{a simple path uses at most } V-1 \text{ edges} \]

As long as there is no negative-weight cycle, the true shortest path between any two vertices is always a simple path — repeating a vertex could only add cost by going around a loop, never save any.

76. Term to definition: Shortest Paths: Dijkstra & Bellman-Ford

Matching

Match the pairs

Match each term to the definition this lesson gave it — not the one you would guess from the word.

  • t1. weight
  • t2. settled
  • t3. priority queue
  • t4. simple path
  • d1. A number attached to an edge, representing its cost: distance, time, price, or anything else you want to minimize along a route.
  • d2. A vertex whose dist value has been declared final and will never be changed again for the rest of the algorithm.
  • d3. A data structure that always hands you the item with the smallest key, efficiently. Here, the key is a vertex's current distance estimate.
  • d4. A path that never repeats a vertex. Since it can visit at most V distinct vertices, a simple path has at most V-1 edges.

Why: These are the working definitions of weight, settled, priority queue, simple path as Shortest Paths: Dijkstra & Bellman-Ford uses them. Pairing them correctly is the test of whether you could state each one with the slide switched off.

77. Decision point: why V minus 1 rounds and not more

Intuition

What move should we make next?

Bellman-Ford relaxes every edge, V minus 1 times.

\[ \text{a shortest simple path has at most } |V| - 1 \text{ edges} \]

That fact is on the table. Turning it into V minus 1 rounds are enough still takes an argument.

What is the claim you would prove by induction, and what does round k buy you? Say the claim precisely before naming the move.

_Look at your toolkit. Say a move number out loud before this slide advances._ A wrong guess is useful. A silent guess is not.

78. Why exactly V-1 rounds suffice

Concept

Here is the key fact: after k full rounds of relaxing every edge, dist is guaranteed correct for every vertex whose true shortest path uses at most k edges.

\[ \text{after round } k: \text{ correct for all shortest paths with} \le k \text{ edges} \]

Since the true shortest path to any vertex is simple (previous slide), it uses at most V-1 edges. So after V-1 rounds, every vertex's shortest distance is guaranteed correct.

\[ \text{longest possible shortest path} = V-1 \text{ edges} \ \Rightarrow\ V-1 \text{ rounds suffice} \]

79. Why is this step legal: Peel the last edge off a shortest path

Explain it to yourself

Discussion prompt

In One round buys one edge this move is made:

Peel the last edge off a shortest path

Why is that legal? Name the rule or definition it rests on before you read on.

Hint: If you can only say "because that is what you do", the rule is the thing to go and find.

Answer:

A shortest path to v using k+1 edges is a shortest path to some u using k edges, plus one edge. By the hypothesis u was correct after round k, and round k+1 relaxes the edge from u to v.

80. One round buys one edge

Concept

The move: #5 (Peel one off), then #6 (Substitute the hypothesis).

Index the claim by number of edges, not by round

Why: Claim: after k rounds, every vertex whose shortest path uses at most k edges has its correct distance. That is the statement with a number in it.

Base case

Why: After 0 rounds the source has distance 0, which is the correct distance for the 0-edge path.

Peel the last edge off a shortest path

Why: A shortest path to v using k+1 edges is a shortest path to some u using k edges, plus one edge. By the hypothesis u was correct after round k, and round k+1 relaxes the edge from u to v.

\[ dist[v] \le dist[u] + w(u, v) = \delta(s, u) + w(u, v) = \delta(s, v) \]

Since no simple path exceeds V minus 1 edges, V minus 1 rounds cover every vertex. The relaxation order inside a round does not matter — the induction never referred to it.

81. The longest possible relay has V-1 hops

Intuition

Picture a relay race with V runners standing at V different vertices. The longest possible baton-passing chain, visiting every runner exactly once, has V-1 handoffs — one fewer than the number of runners.

Each round of Bellman-Ford is like giving the baton one more chance to be passed along. After V-1 rounds, even the longest possible relay chain has had enough chances to complete.

82. What has to happen first: Bellman-Ford trace on the example graph: rounds 1 and 2

Ranking

Put in order

Put the moves of Bellman-Ford trace on the example graph: rounds 1 and 2 into the order they have to happen.

  1. Round 1: relax every edge once, in order
  2. Round 2: relax every edge again, using this round's improving values
  3. Check the estimates after two rounds

Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. D-E and C-E and C-D and B-D all fail, since D, C, or B are still infinity when reached in this order.

83. Bellman-Ford trace on the example graph: rounds 1 and 2

Worked example

Trace Bellman-Ford on graph G1 (S, B, C, D, E) from source S. Process the edges in this order each round: D-E, C-E, C-D, B-D, C-B, S-C, S-B.

rounddist[S]dist[C]dist[B]dist[D]dist[E]
0 (init)0∞∞∞∞

Round 1: relax every edge once, in order

Why: D-E and C-E and C-D and B-D all fail, since D, C, or B are still infinity when reached in this order. S-C succeeds (0+2=2 < ∞) and S-B succeeds (0+4=4 < ∞).

rounddist[S]dist[C]dist[B]dist[D]dist[E]
1024∞∞

Round 2: relax every edge again, using this round's improving values

Why: C-E gives 2+10=12 (< ∞, update). C-D gives 2+8=10 (< ∞, update). B-D gives 4+5=9, which beats the 10 just set, so D improves again to 9. C-B gives 2+1=3, beating B's current 4.

rounddist[S]dist[C]dist[B]dist[D]dist[E]
2023912

Check the estimates after two rounds

Why: D and E are still improving (9 and 12 are not yet their final values), which makes sense — their true shortest paths use more than two edges, so they need more rounds to become correct.

84. Bellman-Ford relaxes everything, repeatedly

Picture it

Animation

Shows: Bellman-Ford relaxes everything, repeatedly — a rendered Manim animation.

Rendered with Manim.

Takeaway: Slower, and it survives negative weights.

85. Plan first: Bellman-Ford trace on the example graph: rounds 3 and 4

Step zero

Discussion prompt

Bellman-Ford trace on the example graph: rounds 3 and 4 — before any calculation: what is the plan? Name the moves in order, in plain English, without doing the arithmetic.

Hint: It starts with: Round 3: relax every edge again

Answer:

  1. Round 3: relax every edge again
  2. Round 4: relax every edge one last time
  3. Verify Bellman-Ford's final distances match Dijkstra's

86. Bellman-Ford trace on the example graph: rounds 3 and 4

Worked example

Continuing from round 2: dist[S]=0, dist[C]=2, dist[B]=3, dist[D]=9, dist[E]=12. This graph has 5 vertices, so V-1 = 4 rounds total are required.

Round 3: relax every edge again

Why: D-E gives 9+2=11, beating the current 12. B-D gives 3+5=8, beating the current 9. The other edges no longer find any improvement this round.

rounddist[S]dist[C]dist[B]dist[D]dist[E]
3023811

Round 4: relax every edge one last time

Why: D-E gives 8+2=10, beating the current 11. No other edge finds any further improvement.

rounddist[S]dist[C]dist[B]dist[D]dist[E]
4023810

Verify Bellman-Ford's final distances match Dijkstra's

Why: S=0, C=2, B=3, D=8, E=10 — exactly the distances Dijkstra found earlier on the same graph. Two very different methods, same correct answer.

\[ dist[S]=0,\ dist[C]=2,\ dist[B]=3,\ dist[D]=8,\ dist[E]=10\ \checkmark \]

87. Watching Bellman-Ford propagate down a chain

Worked example

To see exactly why V-1 rounds are needed, trace Bellman-Ford on a 5-vertex chain, each edge weight 1, source V1. Process edges in this order each round: V4-V5, V3-V4, V2-V3, V1-V2 — deliberately the reverse of the natural direction.

Figure (svg): A chain graph with five vertices V1 through V5 connected in a line, each edge weight 1

Rounds 1 and 2: progress crawls forward one hop at a time

Why: In round 1, only V1-V2 can fire (everything else still involves an infinity), so only V2 improves. In round 2, only V2-V3 can now fire, so V3 improves — but V4 and V5 are still infinity.

rounddist[V1]dist[V2]dist[V3]dist[V4]dist[V5]
101∞∞∞
2012∞∞

Rounds 3 and 4: the last two hops finally complete

Why: Round 3 lets V3-V4 fire, reaching V4. Only in round 4 does V4-V5 finally fire, reaching V5 for the first time.

rounddist[V1]dist[V2]dist[V3]dist[V4]dist[V5]
30123∞
401234

Verify that V5's distance only finalizes in round four

Why: This 5-vertex chain has a longest simple path of exactly 4 edges (V1 to V5), and with this adversarial edge order, the algorithm genuinely needs all 4 = V-1 rounds — not one fewer — to reach V5 at all.

\[ V = 5 \ \Rightarrow\ V - 1 = 4 \text{ rounds needed}\ \checkmark \]

88. Decode the notation: Watching Bellman-Ford propagate down a chain

Notation

Annotate

From Watching Bellman-Ford propagate down a chain — read this one piece at a time. What is each part doing?

On: \( V = 5 \ \Rightarrow\ V - 1 = 4 \text{ rounds needed}\ \checkmark \)

  • In round 1, only V1-V2 can fire (everything else still involves an infinity), so only V2 improves. In round 2, only V2-V3 can now fire, so V3 improves — but V4 and V5 are still infinity.
  • Round 3 lets V3-V4 fire, reaching V4. Only in round 4 does V4-V5 finally fire, reaching V5 for the first time.
  • This 5-vertex chain has a longest simple path of exactly 4 edges (V1 to V5), and with this adversarial edge order, the algorithm genuinely needs all 4 = V-1 rounds — not one fewer — to reach V5 at all.

89. Something is wrong here: stopping Bellman-Ford before V-1 rounds

Anomaly

Predict first

A student writes this, and it looks reasonable:

On the chain graph, a student runs only 2 rounds, notices dist[V4] and dist[V5] haven't changed in a while, and assumes the algorithm has converged.

It is wrong. Say what breaks — and say it before you turn the page.

Correct: This student reports dist[V4] and dist[V5] as infinity — unreachable — which is completely wrong.

Always run the full V-1 rounds, regardless of how things look partway through. 'Nothing changed recently' does not mean 'nothing will change'.

Why: This student reports dist[V4] and dist[V5] as infinity — unreachable — which is completely wrong. Both are reachable, at distances 3 and 4 respectively.

90. Trap: stopping Bellman-Ford before V-1 rounds

Trap

The trap

On the chain graph, a student runs only 2 rounds, notices dist[V4] and dist[V5] haven't changed in a while, and assumes the algorithm has converged.

\[ \text{after round 2: } dist[V4] = \infty, \ dist[V5] = \infty \]

Report the distances after only 2 rounds

Why: This student reports dist[V4] and dist[V5] as infinity — unreachable — which is completely wrong. Both are reachable, at distances 3 and 4 respectively.

\[ \text{reported: unreachable} \quad (\text{actual: } dist[V4]=3,\ dist[V5]=4) \]

The fix

Always run the full V-1 rounds, regardless of how things look partway through. 'Nothing changed recently' does not mean 'nothing will change'.

\[ V = 5 \ \Rightarrow\ \text{run all } V - 1 = 4 \text{ rounds} \]

Run rounds 3 and 4 too

Why: As traced earlier, V4 only becomes reachable in round 3, and V5 only in round 4. Stopping at round 2 misses both, purely because of how the edges happened to be ordered.

\[ dist[V4]=3 \ (\text{round 3}), \quad dist[V5]=4 \ (\text{round 4}) \]

The V-1 bound is about the worst case, not the typical case

Why: Some edge orders converge faster, as seen with the earlier lucky ordering on G1. But the guarantee that ALL graphs are correctly solved only holds if you always run the full V-1 rounds.

91. Which of these survive contact with Shortest Paths: Dijkstra & Bellman-Ford?

Two truths and a lie

Sort into buckets

Some of these hold up and some are the exact mistakes this lesson is built to prevent. Sort them.

Holds up
You have named 14 reusable moves so far. Say as many as you can out loud, by number, from memory.; A path is a sequence of edges chained head to tail. The cost of a path is just the sum of the weights of the edges you used to walk it.; The output is a distance estimate for every vertex, usually called dist. dist of a vertex is the total weight of the cheapest path found so far from the source to it.
Breaks
A student mixes up which side of the comparison is the 'known' side and which is the side being improved.; A student initializes every vertex's distance to 0 'to be safe', instead of only the source.
sound
These are stated as this lesson states them — each one survives the edge cases Shortest Paths: Dijkstra & Bellman-Ford puts it through.
flawed
Each of these is lifted from a trap in this deck: reasonable-sounding, and wrong in a way that only shows up once you rely on it.

92. What has to happen first: Bellman-Ford succeeds where Dijkstra failed

Ranking

Put in order

Put the moves of Bellman-Ford succeeds where Dijkstra failed into the order they have to happen.

  1. Round 1: relax S-A, S-B, A-B in order
  2. Round 2: relax every edge again
  3. Verify the true shortest distance to B is -6

Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. S-A gives dist[A]=0+4=4. S-B gives dist[B]=0+1=1.

93. Bellman-Ford succeeds where Dijkstra failed

Worked example

Return to the negative-weight graph from the Dijkstra trap: S, A, B, with S to A weight 4, S to B weight 1, and A to B weight -10. This graph has 3 vertices, so V-1 = 2 rounds.

Round 1: relax S-A, S-B, A-B in order

Why: S-A gives dist[A]=0+4=4. S-B gives dist[B]=0+1=1. A-B then gives candidate 4+(-10)=-6, which beats the just-set 1 — dist[B] improves to -6, all within round 1.

rounddist[S]dist[A]dist[B]
104-6

Round 2: relax every edge again

Why: S-A gives 4, no change. S-B gives 1, which is not less than -6, no change. A-B gives 4+(-10)=-6, not less than -6, no change. Nothing improves — the values are stable.

rounddist[S]dist[A]dist[B]
204-6

Verify the true shortest distance to B is -6

Why: The two possible routes to B cost 1 (direct) and 4+(-10)=-6 (through A). The smaller of the two, -6, is what Bellman-Ford correctly reports — unlike Dijkstra, which incorrectly reported 1.

\[ \min(1,\ 4+(-10)) = \min(1,-6) = -6\ \checkmark \]

94. The non-negativity requirement, precisely

Picture it

Animation

Shows: The non-negativity requirement, precisely — a rendered Manim animation.

Rendered with Manim.

Takeaway: It is the finality that breaks, not the arithmetic.

95. Speed vs. generality: why not always use Bellman-Ford

Intuition

If Bellman-Ford handles more cases correctly, why not use it everywhere? Because it pays for that generality: it relaxes every edge V-1 times, regardless of how the graph is shaped, while Dijkstra homes in on the answer using a priority queue.

When you know every weight is non-negative — routes, flight prices, most real distance maps — Dijkstra is the faster tool for the job. Save Bellman-Ford for when negative weights are possible, or when you need to check for negative cycles.

96. Bellman-Ford's running time

Concept

Bellman-Ford relaxes every one of the E edges, once per round, for V-1 rounds:

\[ O(V \cdot E) \]

Compare this to Dijkstra's O((V+E) log V). On a dense graph with many edges, Bellman-Ford is noticeably slower — the price paid for correctly handling negative weights.

97. Why is this step legal: 3. Never stop early, even if nothing seems to be…

Explain it to yourself

Discussion prompt

In The Bellman-Ford recipe this move is made:

3. Never stop early, even if nothing seems to be changing

Why is that legal? Name the rule or definition it rests on before you read on.

Hint: If you can only say "because that is what you do", the rule is the thing to go and find.

Answer:

The V-1 bound is a worst-case guarantee; some edge orders converge sooner, but only running the full count guarantees correctness on every graph.

98. The Bellman-Ford recipe

Pattern

1. Initialize dist[source]=0, everyone else infinity

Why: Same setup as Dijkstra — this part of relaxation never changes.

2. Repeat V-1 times: relax every edge in the graph, once each

Why: No priority queue, no 'settled' status — just brute-force repetition over the full edge list.

3. Never stop early, even if nothing seems to be changing

Why: The V-1 bound is a worst-case guarantee; some edge orders converge sooner, but only running the full count guarantees correctness on every graph.

4. Optionally, run one more round to check for a negative cycle

Why: Covered next: if any edge still improves after V-1 rounds, the graph has a negative-weight cycle reachable from the source.

99. Stop as soon as nothing relaxes

Picture it

Animation

Shows: Stop as soon as nothing relaxes — a rendered Manim animation.

Rendered with Manim.

Takeaway: The bound is worst-case; the loop rarely needs all of it.

100. Check yourself: how many rounds?

Check

You are running Bellman-Ford on a graph with 6 vertices.

Check your understanding

What is the minimum number of rounds that guarantees every dist value is correct, on any graph with 6 vertices and no negative cycle?

  • A. 5 (correct)
  • B. 6
  • C. 4
  • D. It depends on the number of edges, not the number of vertices

Answer: A

Why: The number of required rounds is V-1, since the longest possible simple path in a 6-vertex graph has at most 5 edges. With 6 vertices, V-1 = 5 rounds are guaranteed sufficient.

Why B tempts people
This uses V instead of V-1, overcounting by one — a simple path through all 6 vertices has only 5 edges, not 6.
Why C tempts people
This undercounts by one, perhaps confusing V-1 with V-2; a 6-vertex chain graph (like the one traced in this lesson) can genuinely need all 5 rounds under an adversarial edge order.
Why D tempts people
The number of rounds depends only on V, the vertex count — the edge count E affects the cost of EACH round, not how many rounds are needed.

101. Negative Cycles & Choosing an Algorithm

Section

Section 4

102. Negative-weight cycles break the idea of a shortest path

Concept

A negative-weight cycle is a closed loop of edges whose total weight is negative. If such a cycle is reachable from the source, 'shortest path' stops making sense for any vertex reachable through it.

You could always go around the loop one more time and lower your total cost further. There is no minimum — the true 'shortest distance' is unbounded below.

\[ \text{go around the cycle again} \Rightarrow \text{cost keeps dropping, forever} \]

103. Negative edge vs. negative cycle: not the same problem

Concept

A single negative edge, by itself, is not a problem for Bellman-Ford — the earlier worked example proved that directly, correctly finding a distance of -6.

It is only a cycle whose total weight is negative that breaks things. A graph can have many negative edges and still have a perfectly well-defined shortest path for every vertex, as long as none of those edges form a negative-weight loop.

104. Why Dijkstra breaks on negative edges

Picture it

Animation

Shows: Why Dijkstra breaks on negative edges — a rendered Manim animation.

Rendered with Manim.

Takeaway: The greedy commitment is exactly what negative weights invalidate.

105. Why is this step legal: Back up. Use the theorem you just proved instead…

Explain it to yourself

Discussion prompt

In Process: detecting a negative cycle the direct way this move is made:

Back up. Use the theorem you just proved instead of the definition

Why is that legal? Name the rule or definition it rests on before you read on.

Hint: If you can only say "because that is what you do", the rule is the thing to go and find.

Answer:

V minus 1 rounds settle everything if the distances are well defined. So run one extra round: if anything still improves, no finite shortest path exists, which means a negative cycle is reachable.

106. Process: detecting a negative cycle the direct way

Intuition

Watch me not know the answer. This is what the first two minutes actually look like.

We want to report whether the graph contains a negative-weight cycle reachable from the source.

Try enumerating cycles and adding up their weights

Why: It is the definition, so it is guaranteed correct. Find every cycle, total its weights, check for a negative one.

There can be exponentially many cycles

Why: A graph with many parallel routes has a number of cycles that grows exponentially in the vertex count. Correct and unusable.

Dead end. Not a mistake — a move that was worth trying and did not pay off. This happens in most proofs.

Back up. Use the theorem you just proved instead of the definition

Why: V minus 1 rounds settle everything if the distances are well defined. So run one extra round: if anything still improves, no finite shortest path exists, which means a negative cycle is reachable.

One extra pass over the edges, instead of an exponential enumeration. The detection test is a corollary of the correctness proof, which is why the proof was worth doing carefully.

The expert does not see the whole path in advance. The expert tries something, reads the result, and adjusts. That is the skill.

107. Detecting a negative cycle with one more round

Concept

After the normal V-1 rounds finish, run one extra round of relaxing every edge.

If any edge still successfully relaxes — still finds an improvement — during that extra round, the graph contains a negative-weight cycle reachable from the source.

\[ \text{after } V-1 \text{ rounds: any edge still relaxes} \Rightarrow \text{negative cycle exists} \]

Why this works: V-1 rounds are enough for every SIMPLE path. If a distance keeps shrinking past that point, the only way that's possible is by looping through a cycle whose total weight is negative.

108. Teach it back: Detecting a negative cycle with one more round

Explain it

Discussion prompt

Explain Detecting a negative cycle with one more round to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.

Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.

Answer:

After the normal V-1 rounds finish, run one extra round of relaxing every edge.

109. The extra round costs almost nothing

Intuition

One more full pass over every edge is a small, fixed amount of extra work compared to the V-1 rounds you already ran — it does not change the algorithm's overall running time.

For that tiny cost, you get a guarantee: either nothing improves, and your distances are trustworthy, or something improves, and you know for certain not to trust any distance touched by the cycle.

110. By analogy: The extra round costs almost nothing

Analogy

Discussion prompt

Explain The extra round costs almost nothing by analogy to something with no CS3000 Algorithms in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.

Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.

Answer:

One more full pass over every edge is a small, fixed amount of extra work compared to the V-1 rounds you already ran — it does not change the algorithm's overall running time.

111. Picture it first: Bellman-Ford catches a negative cycle

Picture it

Figure (svg): A directed triangle graph with X, Y, Z. Edge X to Y weight 1, edge Y to Z weight negative 3, edge Z to X weight 1, forming a negative-weight cycle

Discussion prompt

Read the picture before the words. What is this showing, and what is the one thing it is built to make obvious? Commit to an answer, then read on.

Hint: Name the parts, then say what changes between them — and if nothing changes, say what is being held still.

Answer:

Vertices X, Y, Z. Source X. Edges: X to Y weight 1, Y to Z weight -3, Z to X weight 1. The cycle X to Y to Z to X totals 1 + (-3) + 1 = -1, a negative-weight cycle.

112. Bellman-Ford catches a negative cycle

Worked example

Vertices X, Y, Z. Source X. Edges: X to Y weight 1, Y to Z weight -3, Z to X weight 1. The cycle X to Y to Z to X totals 1 + (-3) + 1 = -1, a negative-weight cycle.

Figure (svg): A directed triangle graph with X, Y, Z. Edge X to Y weight 1, edge Y to Z weight negative 3, edge Z to X weight 1, forming a negative-weight cycle

Rounds 1 and 2 (V-1 = 2, since V = 3)

Why: Relaxing X-Y, Y-Z, Z-X in order, twice: round 1 gives X=-1, Y=1, Z=-2 (the Z-X relaxation even improves X itself, since -2+1=-1 beats 0). Round 2 gives X=-2, Y=0, Z=-3.

rounddist[X]dist[Y]dist[Z]
1-11-2
2-20-3

Round 3 (the extra detection round)

Why: Relax X-Y again: candidate is -2+1=-1, which is less than the current dist[Y]=0. An edge relaxed successfully after the normal V-1=2 rounds finished.

\[ dist[X] + w(X,Y) = -2 + 1 = -1\ <\ 0 = dist[Y] \]

Verify the extra round still finds an improvement

Why: Since round 3 (beyond the required 2 rounds) still relaxed an edge successfully, this graph contains a negative-weight cycle reachable from the source X — exactly matching the cycle we identified up front, with total weight -1.

\[ \text{round beyond } V{-}1 \text{ still improves} \Rightarrow \text{negative cycle confirmed}\ \checkmark \]

113. Fill in: dist[Y] for Bellman-Ford catches a negative cycle

Comparison

Comparison matrix

From Bellman-Ford catches a negative cycle: refill the dist[Y] column from what you know. The rest of the table is as it appeared.

rounddist[X]dist[Y]dist[Z]
1-11-2
2-20-3

114. One extra pass detects a negative cycle

Picture it

Animation

Shows: One extra pass detects a negative cycle — a rendered Manim animation.

Rendered with Manim.

Takeaway: With a negative cycle there is no shortest path at all — you can always go round again.

115. Running times side by side

Concept

The two algorithms solve overlapping but different problems, at different costs.

AlgorithmHandles negative edges?Detects negative cycles?Running time
DijkstraNoNoO((V+E) log V)
Bellman-FordYesYesO(V · E)

Dijkstra's speed comes precisely from the assumption it cannot safely give up: non-negative weights. Bellman-Ford gives up that speed to stay correct without it.

116. Fill in: Running time for Running times side by side

Comparison

Comparison matrix

From Running times side by side: refill the Running time column from what you know. The rest of the table is as it appeared.

AlgorithmHandles negative edges?Detects negative cycles?Running time
DijkstraNoNoO((V+E) log V)
Bellman-FordYesYesO(V · E)

117. Why is this step legal: 4. If you also need to detect a negative cycle…

Explain it to yourself

Discussion prompt

In Choosing between Dijkstra and Bellman-Ford this move is made:

4. If you also need to detect a negative cycle, run one extra Bellman-Ford round

Why is that legal? Name the rule or definition it rests on before you read on.

Hint: If you can only say "because that is what you do", the rule is the thing to go and find.

Answer:

Any edge that still relaxes after the standard V-1 rounds proves a negative cycle is reachable from the source.

118. Choosing between Dijkstra and Bellman-Ford

Pattern

1. Check whether every edge weight is non-negative

Why: This single check decides everything that follows.

2. If yes, use Dijkstra with a priority queue

Why: Faster, at O((V+E) log V), and always correct when weights are non-negative.

3. If negative weights are possible, use Bellman-Ford

Why: Relax every edge V-1 times; slower at O(V · E), but correct even with negative edges.

4. If you also need to detect a negative cycle, run one extra Bellman-Ford round

Why: Any edge that still relaxes after the standard V-1 rounds proves a negative cycle is reachable from the source.

119. Where this shows up: Shortest Paths: Dijkstra & Bellman-Ford

Real world

Discussion prompt

Outside this lesson: where does Shortest Paths: Dijkstra & Bellman-Ford actually turn up? Name one concrete situation — a job, a piece of software someone ships, a decision somebody has to make — and say which part of Choosing between Dijkstra and Bellman-Ford is doing the work in it.

Hint: Vague is the failure mode here. "Engineering" is not a situation; "deciding whether this build is fast enough to ship" is.

Answer:

That deck builds single-source shortest paths from one shared primitive, edge relaxation. It traces Dijkstra's algorithm by hand with a priority queue and explains why its greedy choice is safe only for non-negative weights, then covers Bellman-Ford's V-1 rounds of relaxation and its negative-cycle detection. It targets the traps of trusting Dijkstra with a negative edge, relaxing in the wrong direction, misjudging why V-1 rounds are needed, and reviving a vertex that has already been settled.

120. How sure are you: Check yourself: negative edge or negative cycle?

Commit first

Predict first

Can Bellman-Ford still compute correct shortest distances for this graph?

Commit to an answer, then rate it — certain, fairly sure, or guessing — and write the rating down before you turn the page.

Correct: Yes — a single negative edge is fine as long as it isn't part of a negative-weight cycle

Why: As shown in the worked example where Bellman-Ford correctly found a distance of -6, negative edges by themselves are not a problem. Only a cycle whose total weight is negative breaks the notion of a shortest path, since it lets you lower your cost forever by looping.

The rating matters as much as the answer: confident-and-wrong is the combination that survives revision, because nothing about it feels like it needs revisiting.

121. Check yourself: negative edge or negative cycle?

Check

A graph has exactly one negative-weight edge, and that edge is not part of any cycle at all.

Check your understanding

Can Bellman-Ford still compute correct shortest distances for this graph?

  • A. Yes — a single negative edge is fine as long as it isn't part of a negative-weight cycle (correct)
  • B. No — any negative edge anywhere makes shortest paths undefined
  • C. No — Bellman-Ford can only be used on graphs with all non-negative weights
  • D. Only if the negative edge touches the source vertex directly

Answer: A

Why: As shown in the worked example where Bellman-Ford correctly found a distance of -6, negative edges by themselves are not a problem. Only a cycle whose total weight is negative breaks the notion of a shortest path, since it lets you lower your cost forever by looping.

Why B tempts people
This confuses 'negative edge' with 'negative cycle'. An isolated negative edge with no cycle around it causes no trouble at all for Bellman-Ford.
Why C tempts people
This describes Dijkstra's limitation, not Bellman-Ford's. Handling negative edges (without cycles) is exactly what Bellman-Ford is designed to do correctly.
Why D tempts people
The edge's position relative to the source doesn't determine whether it's problematic; whether it's part of a negative-weight CYCLE is what matters.

122. Answer it before you see the options: Check yourself: detecting a negative…

Prediction

Predict first

During that extra pass, one edge still successfully relaxes, lowering some vertex's distance further. What does this tell you?

Answer it in your own words, now, with nothing to choose from. The options are on the next slide — and picking the right one off a list is an easier skill than producing it.

Correct: The graph contains a negative-weight cycle reachable from the source

Why: V-1 rounds are proven sufficient for every simple path, the longest kind a true shortest path can be. If a distance can still shrink after that many rounds, the only explanation is a negative-weight cycle being looped through again and again.

123. Check yourself: detecting a negative cycle

Check

You run Bellman-Ford for the standard V-1 rounds, then perform one additional relaxation pass over every edge.

Check your understanding

During that extra pass, one edge still successfully relaxes, lowering some vertex's distance further. What does this tell you?

  • A. The graph contains a negative-weight cycle reachable from the source (correct)
  • B. You made an arithmetic mistake somewhere in the first V-1 rounds and should redo them
  • C. The graph is disconnected, so some vertices were never reached
  • D. That vertex's shortest path happens to use exactly V-1 edges, which is unusual but not a problem

Answer: A

Why: V-1 rounds are proven sufficient for every simple path, the longest kind a true shortest path can be. If a distance can still shrink after that many rounds, the only explanation is a negative-weight cycle being looped through again and again.

Why B tempts people
Continued improvement in the extra round is not a sign of a mistake — it is exactly the intended detection signal Bellman-Ford is designed to produce when a negative cycle exists.
Why C tempts people
A disconnected vertex would stay at infinity throughout, never improving; continued improvement means a route DOES exist, and keeps getting cheaper.
Why D tempts people
A shortest path using exactly V-1 edges would already have been found and stabilized by the end of the V-1 required rounds — it would not still be improving one round later.

124. Rule out three: Check yourself: which algorithm fits?

Elimination

Eliminate the wrong options

Which algorithm should you use, and why?

3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.

  • A. Dijkstra, because all weights are non-negative and it's faster than Bellman-Ford
  • B. Bellman-Ford, because it is always the safer default regardless of the graph
  • C. Dijkstra, because road networks never contain cycles
  • D. Bellman-Ford, because Dijkstra cannot handle graphs with more than a few vertices

Survives elimination: A

Why: Since every travel time is non-negative, Dijkstra's greedy safety argument holds, so it will produce correct results at its faster running time of O((V+E) log V) versus Bellman-Ford's O(V times E).

125. Check yourself: which algorithm fits?

Check

You are given a large road network where every road's travel time is a non-negative number, and you need the single fastest algorithm to find shortest travel times from one city to every other city.

Check your understanding

Which algorithm should you use, and why?

  • A. Dijkstra, because all weights are non-negative and it's faster than Bellman-Ford (correct)
  • B. Bellman-Ford, because it is always the safer default regardless of the graph
  • C. Dijkstra, because road networks never contain cycles
  • D. Bellman-Ford, because Dijkstra cannot handle graphs with more than a few vertices

Answer: A

Why: Since every travel time is non-negative, Dijkstra's greedy safety argument holds, so it will produce correct results at its faster running time of O((V+E) log V) versus Bellman-Ford's O(V times E).

Why B tempts people
Bellman-Ford is not 'always safer' — it is more general (handles negative weights) at the cost of speed. When weights are known to be non-negative, Dijkstra is both correct and faster, so it is the better choice.
Why C tempts people
Road networks routinely contain cycles (loops of streets); Dijkstra's correctness never depended on the graph being acyclic, only on non-negative weights.
Why D tempts people
Dijkstra scales well to large graphs, which is exactly why it is the standard choice for real road-network routing; vertex count is not the deciding factor here.

126. Toolkit update

Concept

Moves added today:

Moves you reused today:

Move #15 is move #8 specialized to things that come in sequences. Instead of the smallest counterexample, you take the earliest point along a path or a run where the claim breaks.

Full toolkit so far: #1 through #15.

Next session opens with you naming every one of these from memory, before any new material.

127. Break it if you can: Toolkit update

Counterexample

Discussion prompt

Move #15 is move #8 specialized to things that come in sequences. Instead of the smallest counterexample, you take the earliest point along a path or a run where the claim breaks.

That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.

Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.

Answer:

Next session opens with you naming every one of these from memory, before any new material.

128. Connect it up: Shortest Paths: Dijkstra & Bellman-Ford

Connect it up

Draw it

One page, no notation unless you need it: draw how these connect — The Shortest-Path Problem · Dijkstra's Algorithm · The Bellman-Ford Algorithm · Negative Cycles & Choosing an Algorithm. Put an arrow wherever one of them is what makes another possible, and label the arrow with why.

129. What you can do now

Recap

Both algorithms in this lesson are built on the exact same move, repeated in different ways.

SituationUse
All weights non-negative, need speedDijkstra: O((V+E) log V)
Negative weights possibleBellman-Ford: O(V · E)
Need to detect a negative cycleBellman-Ford, plus one extra round

Watch for the traps: never trust Dijkstra with a negative edge, never relax backwards, never stop Bellman-Ford before V-1 rounds, and never let a settled Dijkstra vertex be touched again.

Sources

  1. Cormen, Leiserson, Rivest & Stein, Introduction to Algorithms, 4th ed., Ch. 22 (Dijkstra's algorithm) & Ch. 24 (Bellman-Ford) — MIT Press, 2022.
  2. MIT OpenCourseWare 6.006 Introduction to Algorithms, lecture notes on shortest-path algorithms
  3. Every trace in this deck (single-edge relaxation, the full Dijkstra run, all four Bellman-Ford rounds, the chain-graph propagation, and the negative-cycle detection round) was recomputed by hand, edge by edge and round by round, and cross-checked against the closed-form shortest distances. — Verified 2026-07-18.
  4. Northeastern University CS 3000, Algorithms and Data (Summer 2026) — course page and syllabus — course.ccs.neu.edu/cs3000su26. Sets Cormen, Leiserson, Rivest and Stein, Introduction to Algorithms (3rd ed.) as the textbook; listings follow its conventions.
  5. CS 3000 course notes and midterm references circulated by students — github.com/vigneshsaravanakumar404/CS-3000-Algorithms-Data. Notes are typeset with the algpseudocode package, which is the style the listings in this deck follow.

Want this taught 1-on-1? Alexander tutors CS3000 Algorithms — $55/session, free consultation.

Book on Wyzant · Text (657) 465-8108