skip to content

questions

14

Why does Bellman-Ford relax every edge V-1 times rather than once?

level: juniorimportance: must knowfreq 72%

answer

  1. count edges, not vertices
  2. each pass extends routes one hop
  3. cheapest routes never revisit a vertex
  4. a simple route over V vertices
  5. V vertices allow at most V-1 edges

basics

~20 s

After k passes over all edges, Bellman-Ford holds the best route that uses at most k edges. When no negative cycle exists, a best route never repeats a vertex, so it spans at most V-1 edges.

solid answer

~50 s

One pass over every edge extends what the algorithm knows by exactly one hop. The invariant is: after pass `k`, `dist[v]` equals the cost of the cheapest route from the source to `v` using at most `k` edges. If the graph has no negative cycle, some cheapest route to each vertex is simple — any cycle sitting on it has non-negative weight and can be cut out — and a simple route over `V` vertices uses at most `V-1` edges. So `V-1` passes are enough, and no fewer are guaranteed to be. Correctness does not depend on the order edges are scanned in; a lucky order can converge in one pass, which is why the standard early exit is legitimate: if a full pass changes nothing, the estimates are a fixed point and further passes cannot move them.

code

pseudocode · 10 lines
pseudocode
// dist[source] = 0, dist[v] = INF for every other v
for i in 1..V-1:
    changed = false
    for each edge (u, v, w) in E:
        if dist[u] != INF and dist[u] + w < dist[v]:
            dist[v] = dist[u] + w
            pred[v] = u
            changed = true
    if changed == false:
        break

go deeper

for a junior

Be ready to state the invariant in one line — after k passes you have the best route using at most k edges — and to explain that no shortest route repeats a vertex, so V-1 hops is the ceiling.

for a middle

Explain the induction behind the invariant, why relaxation is order-independent, and why the early exit on a change-free pass is sound rather than a heuristic shortcut.

for a senior

Show you know the failure direction: too few passes silently returns an over-large distance that only appears on long chains, so seed your tests with a graph whose optimum genuinely needs V-1 hops.

for a principal

Own the cost argument: O(V*E) with O(V) memory, an early exit that helps typical graphs but not the bound, and a clear statement of which workloads can afford that at your graph's size.

## The state the algorithm carries Bellman-Ford solves single-source shortest paths. It keeps one number per vertex, `dist[v]`, the best route cost found so far from the source, initialised to `0` at the source and to infinity everywhere else, plus optionally `pred[v]`, the vertex you arrived from. Its only move is **relaxation** of a directed edge `(u, v)` with weight `w`: if going to `u` and then taking that edge is cheaper than the current estimate for `v`, take it. ``` if dist[u] + w < dist[v]: dist[v] = dist[u] + w pred[v] = u ``` Two properties of that move matter. First, every value in `dist` is always the cost of some **real** route, so the estimates are upper bounds that only ever fall — the algorithm is never optimistic. Second, relaxation is safe in any order; ordering affects how fast you converge, never whether the final answer is right. ## What one pass buys: exactly one more hop A *pass* means relaxing every edge in the graph once, in whatever order the edge list happens to be in. The invariant that makes the algorithm work is: > After `k` passes, for every vertex `v`, `dist[v]` is the cost of the cheapest route from the source to `v` that uses **at most k edges**. The induction is short. It is true for `k = 0`: only the source is reachable with zero edges. Suppose it holds after `k-1` passes, and let `P` be a cheapest route to `v` using at most `k` edges, whose last edge is `(u, v)`. Chopping that last edge off leaves a cheapest route to `u` using at most `k-1` edges, so `dist[u]` was already correct before pass `k` began. Pass `k` relaxes every edge, including `(u, v)`, so `dist[v]` ends the pass no worse than the cost of `P`. That is the whole idea: **passes count hops learned about, not vertices finished**. This is the point where people who learned a greedy shortest-path algorithm first go wrong — they picture each round finalising one more vertex, nearest first. Bellman-Ford finalises nothing until it stops; it just keeps pushing information one hop further out per pass. ## Why the bound is V-1 Assume the graph has no cycle of negative total weight. Then for every reachable vertex there is a cheapest route that is **simple** — it visits no vertex twice. Reason: if a cheapest route did revisit a vertex, the loop between the two visits has weight at least zero, and deleting it leaves a route that is no more expensive and shorter in hops. A simple route in a graph of `V` vertices touches at most `V` vertices and therefore uses at most `V-1` edges. Feed that into the invariant with `k = V-1` and every reachable vertex is done. The bound is tight. A straight chain of `V` vertices whose edges are listed in reverse order forces the algorithm to learn one hop per pass, using all `V-1`. ## The off-by-one, and which way it fails Stopping after `V-2` passes does not crash and does not loop; it silently returns a distance that is **too large** for any vertex whose only optimum needs exactly `V-1` edges. Because the estimates are always costs of real routes, the error is always in that direction — you get a valid but sub-optimal route, never a fantasy cheaper one. This is a nasty bug in practice: it needs a long optimal chain to show up, so small hand-written tests pass and the failure only appears on production-sized graphs. ## The legitimate early exit If a complete pass relaxes no edge at all, then no edge can ever relax again — nothing feeding it has changed — so the estimates are final and you can stop. On graphs where routes are short in hops this ends after a handful of passes. It is a real and worthwhile speedup, but it does not change the worst case: `V-1` passes over `E` edges is `O(V*E)` time, with `O(V)` space for the distance and predecessor arrays. The converse is the hook for negative-cycle work: if an edge still relaxes on a pass **after** the `V-1`th, some improving walk needs `V` or more edges, and a walk that long must repeat a vertex.

  • If a full pass relaxes nothing, may you stop early — and does that change the worst case?
    Yes, you may stop. No edge can relax again once a whole pass changed nothing, because relaxation only fires when an endpoint's estimate has dropped; the estimates are a fixed point. It is a genuine speedup on graphs whose optimal routes are few hops deep, but the worst case is unchanged at O(V*E) — a long chain scanned in an unhelpful edge order still needs all V-1 passes.
  • Does the order you iterate the edges in change the final answer?
    No. Relaxation is safe in any order, so the result after V-1 passes is the same for every ordering. Order changes only how fast you converge: scanning edges in the order they appear along optimal routes finishes in one pass, and in a directed acyclic graph a topological order finishes in one pass by construction. The worst-case bound assumes the least helpful order.
  • What exactly goes wrong if you run only V-2 passes?
    A vertex whose only optimal route uses exactly V-1 edges keeps a distance that is too large — the cost of some shorter-in-hops, more expensive route. There is no error, no warning, and the answer stays a valid route, just not the cheapest. It surfaces only on graphs with long optimal chains, so small tests will not catch it.

Each pass is a round of gossip: after k rounds, everyone who is within k handshakes of the source has heard the best version of the story. With V people, no chain of fresh handshakes is longer than V-1.

saying these in an interview costs you the question

  • Says V-1 is an arbitrary safety margin with no argument
  • Claims a single pass over all edges is enough
  • Counts passes as vertices settled, as in a greedy algorithm
  • Thinks a particular edge iteration order is required for correctness
  • Believes passes beyond V-1 keep lowering distances on a normal graph

context

open as a page

What does Dijkstra's algorithm compute on a travel-time road map, and in what order does it finalize vertices?

level: juniorimportance: must knowfreq 84%

basics

~20 s

Dijkstra computes the minimum total travel time from one source to every reachable intersection - cheapest total weight, not fewest road segments. Vertices are finalized in non-decreasing distance order, so once one is popped its distance never changes.

open as a page

What does Floyd-Warshall compute, and what are its time and space complexities?

level: juniorimportance: must knowfreq 70%

basics

~10 s

Floyd-Warshall computes the shortest-path distance between every ordered pair of vertices in a single run, not from one source. It costs O(V^3) time through three nested loops and O(V^2) space for the distance matrix.

open as a page

Why does an edge that still relaxes on Bellman-Ford's V-th pass prove a negative cycle?

level: middleimportance: must knowfreq 64%

basics

~20 s

A further improvement means some cheaper walk uses V or more edges. A walk that long must repeat a vertex, and the loop it encloses can only reduce the total if its own weight is negative.

open as a page

Where do the log factors in Dijkstra's O((V + E) log V) binary-heap bound come from?

level: middleimportance: must knowfreq 72%

basics

~20 s

Each vertex is extracted from the min-heap once at O(log V), giving V log V. Each edge triggers at most one priority update, also O(log V), giving E log V. The two terms sum to O((V + E) log V).

open as a page

Does Floyd-Warshall produce correct distances when some edge weights are negative?

level: middleimportance: must knowfreq 62%

basics

~20 s

Yes, provided no cycle has negative total weight. The recurrence never finalises a vertex early, so a cheap route found late still improves an entry. With a negative cycle no shortest path exists and the output is meaningless.

open as a page

Which Dijkstra invariant breaks when one link in a latency graph has a negative weight?

level: seniorimportance: must knowfreq 76%

basics

~20 s

The finality invariant breaks: Dijkstra assumes an extracted vertex's distance can never improve, which holds only because remaining edges add non-negative amounts. One negative edge lets a cheaper route appear after a vertex is settled, and the wrong value propagates.

open as a page

In A* on a road map, what must the heuristic guarantee for the returned route to stay optimal?

level: middleimportance: should knowfreq 52%

basics

~20 s

The heuristic must be admissible: it may never overestimate the true remaining cost to the goal. A* orders its frontier by cost-so-far plus heuristic, and admissibility is what stops it finalizing the goal before a cheaper route surfaces.

open as a page

In Floyd-Warshall's triple loop, why must the intermediate-vertex loop k be outermost?

level: middleimportance: should knowfreq 55%

basics

~20 s

The k loop is outermost because each pass must finish adding waypoint k for every pair before k+1 begins. That preserves the invariant that D[i][j] holds the best cost using waypoints up to k; reordering leaves distances too large.

open as a page

Why precompute all pairs with Floyd-Warshall for 400 pick stations instead of 400 single-source runs?

level: seniorimportance: should knowfreq 48%

basics

~20 s

At 400 stations the travel-time graph is dense, so 400 queue-driven searches cost more than one triple loop of roughly 64 million add-and-compare steps. The loop yields the same matrix and makes every later query an O(1) lookup.

open as a page

When do you accept Bellman-Ford's O(V*E) instead of removing negative rebate edges to use Dijkstra?

level: principalimportance: should knowfreq 34%

basics

~10 s

Accept it when the negative edges are part of the real cost model and the queries are few or offline. Deleting or flattening them makes the algorithm faster by answering a different question.

open as a page

Why does Bellman-Ford need -log of each exchange rate to spot arbitrage?

level: seniorimportance: nice to knowfreq 38%

basics

~20 s

Rates compound by multiplying while route costs add, and profit means a product above one. Taking the logarithm turns the product into a sum, and negating turns "above one" into "below zero" — exactly a negative cycle.

open as a page

In lazy-deletion Dijkstra, what breaks if a vertex popped a second time is never skipped?

level: seniorimportance: nice to knowfreq 30%

basics

~20 s

Nothing breaks in the output: with non-negative weights the strict-improvement test rejects every update a stale pop could attempt. The damage is performance - each stale pop re-scans a settled vertex's whole adjacency list, and heap entries grow toward one per relaxation.

open as a page

Floyd-Warshall builds your travel-time matrix nightly, but aisles close mid-shift — recompute or patch?

level: principalimportance: nice to knowfreq 22%

basics

~20 s

Decide by direction of change. A cheaper edge patches in O(V^2); a closed aisle makes routes more expensive, has no cheap patch, and forces a rerun. Serve stale distances only where the error is bounded and visible.

open as a page