Home/Data structures & algorithms/Bellman–Ford shortest paths

Bellman–Ford shortest paths

Relax all edges and detect source-reachable negative cycles

A workflow simulator charges for some transitions and credits others. A route that looks expensive partway through may become cheap after a later credit, so settling that intermediate cost too early can miss the best result.

Bellman–Ford repeatedly revisits the edges instead. It also exposes a more serious modelling issue: a reachable cycle that earns more credit each time around has no finite cheapest route through it.

Allowing credits in a workflow cost model

Bellman–Ford relaxes every directed edge repeatedly. After i passes, distances cover paths of at most i edges. Without a reachable negative cycle, a cheapest path can be simple, so n-1 passes suffice.

Letting improvements cross another edge

Consider edges listed as 1 → 2: -2, 0 → 1: 4, and 0 → 2: 7. The first pass can't use the first edge yet; later edges make 1 reachable. The next pass improves 2 from seven to two. Edge order can let an in-place pass propagate farther, so the guarantee is at least one more edge of progress, not exactly one.

go
value := func(n int) *int { return &n }
edges := [][3]int{{1, 2, -2}, {0, 1, 4}, {0, 2, 7}}
distance := []*int{value(0), nil, nil}
for pass := 0; pass < 2; pass++ {
	for _, edge := range edges {
		u, v, weight := edge[0], edge[1], edge[2]
		if distance[u] == nil {
			continue
		}
		candidate := *distance[u] + weight
		if distance[v] == nil || candidate < *distance[v] {
			distance[v] = value(candidate)
		}
	}
}
fmt.Println(*distance[1], *distance[2]) // 4 2 after both passes.

Recognising an endlessly cheaper cycle

A further improvement from a reachable vertex proves a reachable negative cycle. An isolated negative cycle does not affect this source. Never relax from an unreachable sentinel; adding a negative edge to an invented infinity can manufacture a false route. The slower algorithm supports signed edge weights. Build private working state. The Go API uses nil for absence and assumes finite cost arithmetic fits int.

Initializing V distances and scanning E edges up to V-1 times takes O(V+VE) time, plus an extra cycle-detection scan. Distances use O(V) state beyond the edge list. A pass with no changes can stop early. Negative edges in an unreachable component must remain unreachable from this source.

Running more passes cannot turn the simulator’s reachable negative cycle into a finite cheapest route.

Practice Bellman–Ford shortest paths

Implement the exercise in a full-screen workspace, then run its tests.

Open practice
Next lessonFloyd–Warshall all-pairs shortest paths