Bellman–Ford

Graphs
avg O(V·E)

Bellman-Ford finds the cheapest path from one node to every other node, even when some edges have negative cost. It is the patient sibling of Dijkstra: no clever queue, no greedy picks - it just relaxes every edge, up to V-1 times, and that patience makes it honest about negative weights. As a bonus, one extra pass tells you whether the graph has a negative cycle, where 'cheapest' stops meaning anything. This relax-everything idea once ran the early internet: RIP routers are nodes doing Bellman-Ford on each other.

Watch every edge relax

Press play - or drag the timeline and step through it yourself.
Iteration 1Improvements 0Step 1 / 27
5-426339Ad=0Bd=∞Cd=∞Dd=∞Ed=∞Fd=∞

Find the cheapest path from A to every node. One edge is negative: C→D costs -4. No queue, no priorities - just relax all 7 edges, again and again, in a fixed order.

just improved reached, may still improve final distance the negative-edge path best incoming edge

Complexity

Best
O(E)
Input already in order
Average
O(V·E)
Normal mixed input
Worst
O(V·E)
Worst possible input
Space
O(V)
Extra memory used

A group chat of delivery deals

You post a package from your city, A, and five friends want to know the cheapest cost for it to reach them. Nobody sees the whole map - there is only a list of courier routes with prices. So the chat runs rounds: every round, every route is checked once, asking 'best cost into my start city, plus my fee - is that cheaper for the city I end in?'. One route is a promo that pays 4 back for using it. A greedy planner would lock answers in early and miss the promo, but the rounds keep re-checking everything, so the promo's saving spreads to every city behind it. When a whole round changes nothing, the prices are final.

How it works, step by step

  1. Set the start's distance to 0 and every other node to infinity (not reached yet).

  2. Walk the edge list in a fixed order. For each edge u→v with weight w: if `dist[u] + w < dist[v]`, write the smaller value. This check is called relaxing the edge.

  3. One full sweep over all edges is one iteration. Each iteration lets the best-known costs travel at least one edge further from the start.

  4. Repeat up to V-1 times. A shortest path can use at most V-1 edges, so that is always enough - no matter how unlucky the edge order is.

  5. If an iteration improves nothing, stop early. A second identical sweep would see the same numbers and change nothing either.

  6. Safety check: run one extra iteration. If anything still improves, the graph has a negative cycle and 'shortest path' has no meaning.

The code, in JavaScript

The whole algorithm: V-1 sweeps over the edge list, plus the early-exit flag. This is the graph from the animation - with this edge order it settles in one sweep; a worse order just needs more sweeps, never a different answer.

javascript
function bellmanFord(nodes, edges, start) {
  const dist = Object.fromEntries(nodes.map((n) => [n, Infinity]));
  dist[start] = 0;

  // A shortest path uses at most V-1 edges, so V-1 sweeps always suffice.
  for (let i = 0; i < nodes.length - 1; i++) {
    let improved = false;

    for (const [from, to, w] of edges) {
      // Relax: can from's best cost plus this edge beat to's best?
      // Infinity + w is still Infinity, so unreached nodes offer nothing.
      if (dist[from] + w < dist[to]) {
        dist[to] = dist[from] + w;
        improved = true;
      }
    }

    if (!improved) break;   // a full sweep changed nothing → we are done
  }

  return dist;
}

const edges = [
  ["A", "B", 3], ["A", "C", 9], ["B", "D", 5],
  ["C", "D", -4],              // negative edge: D is cheapest via C
  ["D", "E", 2], ["D", "F", 6], ["E", "F", 3],
];

bellmanFord(["A", "B", "C", "D", "E", "F"], edges, "A");
// → { A: 0, B: 3, C: 9, D: 5, E: 7, F: 10 }

Dry run: Bellman-Ford from node A

The same steps the visualizer plays, written as a table. Generated by running the real algorithm - not written by hand.

StepIterationWhat happened
11Improve B: ∞ → 3 via A.
21Improve C: ∞ → 9 via A.
32Improve D: ∞ → 8 via B.
42Improve D: 8 → 5 via C. The -4 edge pays off. Dijkstra had already locked D in at 8 - and would have shipped the wrong answer.
52Improve E: ∞ → 7 via D.
62Improve F: ∞ → 11 via D.
72Improve F: 11 → 10 via E. F's best incoming edge re-points from D→F to E→F.
83Relax B→D: 3 + 5 = 8 is not better than 5. No change.
93Relax C→D: 9 - 4 = 5 is not better than 5. No change.
103Relax D→E: 5 + 2 = 7 is not better than 7. No change.
113Relax D→F: 5 + 6 = 11 is not better than 10. No change.
123Relax E→F: 7 + 3 = 10 is not better than 10. No change.
133Relax A→B: 0 + 3 = 3 is not better than 3. No change.
143Relax A→C: 0 + 9 = 9 is not better than 9. No change.
153Iteration 3 relaxed all 7 edges and improved nothing. Safe to stop: another pass would see the exact same numbers, so nothing can ever change again.

Good choice when…

  • Some edges are negative - refunds, cashback, energy regained downhill. Dijkstra's greedy promise breaks there; Bellman-Ford does not care about the sign.
  • You need to detect negative cycles: currency arbitrage, broken cost models, 'this constraint system has no solution'.
  • The setting is distributed and each node only talks to neighbours - RIP routing is Bellman-Ford run by routers gossiping their distance tables.
  • All you have is a flat edge list. No adjacency structure, no priority queue - the whole algorithm is ten lines.

Bad choice when…

  • Every weight is non-negative and speed matters. Dijkstra with a heap is O(E log V) against O(V·E) - on a big graph that is milliseconds against minutes.
  • The graph is unweighted - BFS already gives shortest paths in O(V+E), with no arithmetic at all.
  • The graph has no cycles (a DAG) - one relax pass in topological order beats V-1 sweeps and handles negative edges too.

Common mistakes

  • It relaxes edges, not nodes. There is no queue and no visiting order - people carry over their Dijkstra mental model and add one, which either breaks correctness on negatives or quietly rebuilds Dijkstra.
  • V-1 iterations is the worst case, not the plan. With the early-exit flag most graphs settle in a few sweeps - forget the flag and every run pays the worst case.
  • A negative edge is fine; a negative cycle is fatal - one more lap is always cheaper, so 'shortest' stops existing. On untrusted input, always run the one extra detection pass.
  • `Infinity + w` is still `Infinity` in JavaScript, so unreached nodes offer nothing. Swap Infinity for a big number like 1e9 and `1e9 + w` suddenly wins comparisons - inventing paths out of unreachable nodes.

Bellman–Ford vs. its closest relatives

AlgorithmBestAverageWorstSpaceStable
Bellman–Fordthis pageO(E)O(V·E)O(V·E)O(V)-
Dijkstra's AlgorithmO(E log V)O(E log V)O(E log V)O(V)-
Breadth-First SearchO(V + E)O(V + E)O(V + E)O(V)-
Topological SortO(V + E)O(V + E)O(V + E)O(V)-