Basis Lab

Answers · Making it fast enough

Why does breadth-first search always find the path with the fewest links?

In shortBreadth-first search meets points in order of how many links they are from the start, so the first time it reaches a point it has used the fewest possible links.

The first time breadth-first search reaches a point, it has used the fewest possible links, because points leave the waiting line in strict order of how many links from the start they are. A shorter route would have to come through a point in an earlier ring, and that point's neighbours were added before any later ring was touched.

That is the whole reason. The rest is the arithmetic of the line.

The order the line produces

Put the start in a line. Take from the front, look at its neighbours, and put any neighbour not seen before at the back. On the six-point graph with links a-b, a-c, b-d, c-d, d-e and e-f, start at a. Remove a: b and c are unseen, so both are marked at one link and put in the line as b, c. Remove b: d is unseen, marked at two links, and the line becomes c, d. Remove c: d is already seen, so nothing is added. Remove d: e is unseen, marked at three links. Remove e: f is unseen, marked at four links. Remove f: nothing new. The distances are a at 0, b at 1, c at 1, d at 2, e at 3, f at 4, each one obtained as the distance of the point that reached it plus one. The c-to-d link is the informative one: d was already marked when b looked at it, so c cannot add it a second time. That is not housekeeping for its own sake. It is why d has one distance, 2, rather than two competing distances.

FIG 1Spreading out from a, one ring at a time
stepsteptaken from the frontits neighboursnewly addedthe line nowwhat happened
11ab, cb, cb, ca is at 0 links; b and c are marked at 1 link each.
22ba, ddc, da is already seen; d is marked at 2 links, one more than b.
33ca, dnothingdd is already seen from b, so c adds nothing.
44db, c, eeeb and c are seen; e is marked at 3 links.
55ed, ffff is marked at 4 links.
66fenothingempty, donee is seen; no new points.
6 steps
The first ring is b and c, the second is d, the third is e, the fourth is f. Step three is the check that stops d being added twice.

Why a later shorter route cannot exist

Suppose a point vv is first reached at distance kk, but there is a route to vv with jj links where j<kj < k. Take a point uu on that route one step before vv. The route reaches uu in j−1j-1 links, so uu is at distance at most j−1j-1. Since j−1<k−1j-1 < k-1, every point at distance j−1j-1 leaves the line before any point at distance k−1k-1 is served. When uu leaves the line, every neighbour not yet seen is marked and put at the back, and vv is one of those neighbours. So vv is marked at distance at most jj, before the ring at distance k−1k-1 is reached. That contradicts vv being first reached at kk. The first arrival is not a lucky one: a shorter route would have forced an earlier arrival.

FIG 2The distance of a point, built from its neighbours
the fewest links from the start to the point v
any point u with a link to v
The distance to a point is one more than the distance to the nearest point that links to it. The ring method computes this without ever evaluating the minimum, because it reaches v from the nearest such u first by construction.

The natural guess is that the first arrival is shortest because the walk looks tidy when the rings are drawn by hand, with distances appearing in ascending order. Tidiness is not the mechanism. The mechanism is that all points at distance rr are taken out of the line before any point at distance r+1r+1, so when a point at distance rr is taken out, its unseen neighbours are exactly the points that should next be marked at distance r+1r+1. If marking is delayed until a point is taken out of the line rather than when it joins, the same point can be put in the line several times by several different neighbours. The printed distances can still come out right, which is the dangerous part, but the line fills with duplicates and the work and memory grow for no gain. The invariant that carries the proof is the placement of the mark, not the shape of the drawing.

What changes when links differ

The guarantee is exactly and only true when every link counts the same. The line orders points by number of links, not by total cost, so if links carry different costs, a route with fewer links can be more expensive than a route with more links. Then a point reached early by the line may not be reached cheaply, and the first-arrival argument has nothing to stand on. The repair is to serve the cheapest known point next rather than the oldest, which is a priority line instead of a waiting line. The memory picture also changes with scale: the line must hold a whole ring at once, and on a graph where every point has hundreds of neighbours the rings multiply by hundreds each step, so the widest ring, not the number of points, is what limits the walk.

Worth keeping

  • The first arrival at a point is shortest because every point one link closer was taken out of the line earlier, and its neighbours were added then.
  • Marking a point as seen when it joins the line, not when it leaves, prevents duplicates; delaying the mark can keep the answer but wastes work and memory.
  • The shortest-path guarantee depends on every link costing the same; with unequal costs the queue order no longer matches the cheapest route.

Where this goes next

This question is one step of Graphs and Finding a Path, a course that works through its subject from the beginning. The page that teaches this part of it is Spreading Out One Ring at a Time, and it reads the whole way through whether or not you have an account.

What an account changes is the practice: problems standing under every idea, marked with a reason rather than a tick, in a copy of the course that is yours.

Read that pageThe whole course

Other questions people ask about this

  1. Why doesn't breadth-first search give the cheapest path once the links have different costs?Breadth-first search counts links rather than costs, so it can return a route with fewer links that is more expensive than a longer route.
  2. How do I know when there is no order that satisfies all the dependencies?If you repeatedly remove anything with nothing still waiting on it and cannot remove everything, the dependencies contain a loop, so no valid order exists.
  3. How do I find out if a graph is really in two separate pieces?Walk from one point, mark everything you can reach, then start again at any unmarked point; the number of walks is the number of separate pieces.
  4. Why is it safe to keep taking the cheapest link that doesn't create a loop?Because the cheapest link joining two separate pieces is the cheapest way across a split, and swapping it into any rival solution cannot raise the total cost.
  5. Why is O(2n) treated the same as O(n)?Because it describes how cost grows rather than exact cost, doubling every cost does not change the growth class.
  6. How does a hash function turn a word into an array index?A hash function reads the word as bytes, mixes them into one large number, then takes the remainder after dividing by the table size to get an index from zero to size minus one.

Read alongside