Origins and the Shared Idea
Breadth-first search is the natural shortest-path algorithm when every move has the same cost: its FIFO queue processes vertices one distance layer at a time. The two techniques in this article preserve that useful order while exploiting extra structure in the problem.
One principle, two different shortcuts
BFS Both endpoints are known, so two ordinary BFS waves can meet near the middle instead of one wave reaching all the way across.
The names sound related because both contain “BFS,” but they solve different kinds of problems. 0-1 BFS changes how vertices are ordered; bidirectional BFS changes where the exploration begins. They can even be combined, but the stopping condition then needs the same care as bidirectional Dijkstra.
Choose the Right Search
Costs are 0 or 1
Use 0-1 BFS for one source to one or many destinations. A 0-cost edge goes to the front; a 1-cost edge goes to the back.
weighted single source dequeOne source, one target
Use bidirectional BFS when edges are unweighted and the target is known. Search from both ends and join the parent chains.
unweighted single pair two queues| Graph condition | Best starting point | Why |
|---|---|---|
| Every edge has equal cost | Ordinary BFS | A FIFO queue already gives distance order. |
| Every weight is exactly 0 or 1 | 0-1 BFS | A deque replaces the heap and keeps linear time. |
| Arbitrary non-negative weights | Dijkstra | A priority queue is needed to select the smallest tentative distance. |
| Unweighted, one known source-target pair | Bidirectional BFS | Two shallower searches often inspect far fewer vertices. |
0-1 BFS: A Two-Level Priority Queue
Let each edge weight be $w \in \{0,1\}$. Relaxation is exactly the same as in Dijkstra's algorithm:
$$\text{if } dist[u] + w(u,v) < dist[v], \quad dist[v] \leftarrow dist[u] + w(u,v).$$
The specialization is in where the improved vertex goes. A 0-edge creates work at the current distance, so it belongs at the front. A 1-edge creates work for the next distance layer, so it belongs at the back.
appendleft(v) for $w=0$ and append(v) for $w=1$.The invariant that replaces a heap
Suppose the vertex at the front has distance $d$. Every vertex already waiting in the deque has distance $d$ or $d+1$. Relaxing a 0-edge creates another $d$-vertex and places it before the $d+1$ group; relaxing a 1-edge creates a $d+1$-vertex and places it after the $d$ group.
That is exactly the amount of ordering this weight set needs. A general-purpose priority queue would work, but it would spend $O(\log V)$ time maintaining distinctions that can never occur.
Bidirectional BFS: Meet Near the Middle
Bidirectional BFS applies to an unweighted source-to-target query. One BFS grows from $s$ and another grows from $t$. If the shortest path has $d$ edges and the local branching factor is roughly $b$, an idealized one-way search may expose about $b^d$ states, whereas two balanced searches expose roughly
$ 2b^{d/2}\quad\text{instead of}\quad b^d. $
This is a geometric intuition, not a better worst-case bound: either method can still visit the whole graph, so the graph-theoretic worst case remains $O(V+E)$.
Directed graphs need reverse edges
The search from $t$ must answer “which vertices can reach me?” For a directed graph, run that side over the transpose graph, where every edge is reversed. Reusing the forward adjacency list is correct only when the graph is undirected.
Worked Examples and Failure Intuition
0-1 BFS trace: why a permanent visited flag is dangerous
Use source 0 and directed edges $(0,1,1)$, $(0,2,0)$, $(2,3,0)$, and $(2,1,0)$. Vertex 1 first receives distance 1, but the later route $0\rightarrow2\rightarrow1$ costs 0.
| Action | Successful relaxation | Deque after action | Known distances |
|---|---|---|---|
| Initialize | — | [0] | d[0]=0 |
| Pop 0 | $0\to1$ costs 1; $0\to2$ costs 0 | [2, 1] | d[2]=0, d[1]=1 |
| Pop 2 | $2\to3$ costs 0; $2\to1$ improves 1 to 0 | [1, 3, 1] | d[1]=0, d[3]=0 |
| Pop 1 | No improvement | [3, 1] | d[1]=0 is final |
| Finish | The stale second copy of 1 changes nothing | [] | [0, 0, 0, 0] |
Do not copy ordinary BFS's visited-on-enqueue rule
In ordinary BFS, the first discovery is shortest because every edge adds one. In 0-1 BFS, a vertex discovered through a 1-edge can later improve through zero-cost edges. Use the relaxation test against dist[v]; do not forbid a useful re-enqueue merely because $v$ was seen before.
Bidirectional trace: six edges become two depth-3 searches
For the path $S\!\to a\!\to b\!\to M\!\to c\!\to d\!\to T$, one-way BFS must reach depth 6. With alternating layers, the forward side knows $b$ at depth 2 and then $M$ at depth 3; the backward side similarly reaches $M$ at depth 3. The meeting distance is
$$dist_S[M] + dist_T[M] = 3 + 3 = 6.$$
The saving becomes dramatic when every vertex has many irrelevant neighbors: reducing the explored depth reduces the entire branching tree, not just the six vertices on the final path.
Path Reconstruction
Distances answer “how short?” Parent pointers answer “which route?” The two algorithms store them slightly differently.
0-1 BFS predecessor
Whenever an edge improves dist[v], set parent[v] = u. After the algorithm finishes, follow parents from the destination back to the source and reverse the list.
Update the parent only on a strict distance improvement, exactly where relaxation succeeds.
Two parent forests
parentFromStart[v] points toward $s$. parentToTarget[v] points toward $t$. At meeting vertex $m$, build $s\leadsto m$, then append the chain after $m$ toward $t$.
Include the meeting vertex once. Duplicating $m$ is the most common reconstruction bug.
Complexity Without the Hand-Waving
| Algorithm | Worst-case time | Auxiliary space | Practical search volume | Requirement |
|---|---|---|---|---|
| 0-1 BFS | $O(V+E)$ | $O(V)$ | Each successful label change schedules constant-time deque work. | Weights exactly in $\{0,1\}$ |
| Ordinary BFS | $O(V+E)$ | $O(V)$ | Up to about $b^d$ states in a tree-like search. | Equal edge costs |
| Bidirectional BFS | $O(V+E)$ | $O(V)$ | Ideally about $2b^{d/2}$ states. | Unweighted, known target |
| Dijkstra with heap | $O((V+E)\log V)$ | $O(V)$ | Handles all non-negative weights. | Non-negative weights |
The shortest mental model: 0-1 BFS is Dijkstra with only two possible priority levels; bidirectional BFS is ordinary BFS with two origins and a join.
Ask what structure the input guarantees before choosing either optimization.
Implementations
Each tab contains both algorithms. The 0-1 routine validates its weight contract; the bidirectional routine returns a path and accepts both the forward and reverse adjacency lists. For an undirected graph, those two lists are the same object.
Real-World Applications
Free and paid moves
In a grid, continuing in the current direction might cost 0 while changing direction costs 1. Teleports, preferred roads, and “minimum walls broken” problems have the same binary-cost structure.
Use: 0-1 BFS from the starting state.
Degrees of separation
When looking for one connection chain between two known profiles, two frontiers can meet long before a one-way social-graph crawl reaches the destination.
Use: bidirectional BFS on an unweighted relationship graph.
Implicit state spaces
Word ladders, lock combinations, and small puzzles often generate neighbors on demand. Searching from both known configurations can sharply reduce generated states.
Use: bidirectional BFS when reverse moves are available.
Routing with preferences
A transition can encode “preferred” as cost 0 and “penalized” as cost 1, letting the objective minimize the number of undesirable transitions rather than physical length.
Use: 0-1 BFS only when the model truly has two additive costs.
Exercises
Check the invariants
- For the directed edges $s\to a$ (1), $s\to b$ (0), $b\to a$ (0), and $a\to t$ (1), write the deque after every successful relaxation.
- Construct the smallest example where marking a 0-1 BFS vertex permanently visited when first enqueued gives the wrong distance.
- Prove by induction that the deque contains only two consecutive distance values and that all smaller labels appear first.
Hint for 2: let one vertex be reachable directly by cost 1 and indirectly through two zero-cost edges.
Reason about two-way search
- Run alternating-layer bidirectional BFS on a path of length 7. At which layer does the first intersection appear?
- For a directed graph, give an example where using the original adjacency list from the target incorrectly reports “no path.” Then fix it with the transpose.
- Challenge: modify the implementation to expand the smaller frontier while retaining distances and a provably safe stopping condition.
A safe weighted-style rule tracks the best complete path seen and stops only when the minimum possible unfinished path cannot beat it.
Limitations
| Pitfall | Why it fails | Better choice or repair |
|---|---|---|
| A 0-1 edge has weight 2 or -1 | The two-level deque invariant disappears. | Use Dijkstra for non-negative weights or Bellman-Ford when negative edges are possible. |
| Scaling $\{0,W\}$ without explanation | The code expects 0 and 1, not arbitrary $W$. | If $W>0$ is the only positive weight, divide all weights by $W$, run 0-1 BFS, then multiply finite distances by $W$. |
| No known target | There is nowhere to seed the reverse search. | Use ordinary BFS or 0-1 BFS for all-destination distances. |
| Backward search follows forward directed edges | It explores vertices reachable from $t$, not vertices that can reach $t$. | Build and search the transpose graph. |
| Stop when any two discovered sets touch | With unbalanced or weighted expansion, the first touch need not certify the best total distance. | Expand complete balanced BFS layers, or maintain a best path plus a lower-bound termination test. |
Optimization is conditional, not automatic
Bidirectional BFS can use more memory than expected because it stores two visited sets, and it may offer little benefit on narrow paths, highly asymmetric graphs, or when reverse neighbors are expensive to generate. 0-1 BFS is excellent inside its exact weight contract and invalid outside it.