A Bit of History
Standard Breadth-First Search (BFS) was introduced by Edward F. Moore in 1959 to find shortest paths in unweighted graphs. When edge weights are binary (e.g. $\{0, 1\}$ or $\{0, W\}$), competitive programmers and algorithm researchers realized that a double-ended queue (deque) maintains the monotonic distance property without needing an $O(\log V)$ priority queue.
Meanwhile, Ira Pohl introduced Bidirectional Search in 1969 ("Bi-directional Search in Path Finding Problems"). By launching two searches simultaneously — one forward from source $S$ and one backward from target $T$ — Pohl demonstrated that search space shrinks dramatically from $O(b^d)$ to $O(b^{d/2})$, where $b$ is the branching factor and $d$ is the path distance.
0-1 BFS: Double-Ended Queues
In standard BFS, a regular FIFO queue ensures vertices are popped in non-decreasing order of distance. If edge weights are restricted to $0$ and $W$ (commonly $0$ and $1$):
- When relaxing edge $(u, v)$ with weight $w = 0$: $dist[v] = dist[u]$. Push $v$ to the FRONT of the deque.
- When relaxing edge $(u, v)$ with weight $w = 1$: $dist[v] = dist[u] + 1$. Push $v$ to the BACK of the deque.
Why Does 0-1 BFS Work?
At any moment, the distances of nodes in the deque differ by at most 1 (i.e. all nodes in the deque have distance $k$ or $d + 1$). Pushing weight 0 nodes to the front ensures that all distance $k$ nodes are processed before any distance $k+1$ nodes!
Bidirectional Search
Standard single-source shortest path algorithms explore a ball of radius $d$ around source $S$, visiting $O(b^d)$ nodes. Bidirectional search explores two smaller balls of radius $d/2$ — one centered at $S$ and one centered at $T$:
$$b^{d/2} + b^{d/2} = 2 \cdot b^{d/2} \ll b^d$$
flowchart LR
S((Source S)) -->|Forward Frontiers| M((Meeting Node M))
T((Target T)) -->|Backward Frontiers| M
style S fill:#3B9797,stroke:#132440,color:#ffffff
style T fill:#BF092F,stroke:#132440,color:#ffffff
style M fill:#16476A,stroke:#132440,color:#ffffff
When searching with Dijkstra, the forward search maintains $dist_F[]$ and the backward search maintains $dist_B[]$. The algorithm terminates when a vertex $u$ is extracted from either priority queue that has been visited by both directional searches. The shortest path length is $\min_{v} \{ dist_F[v] + dist_B[v] \}$.
Worked Examples
0-1 BFS on 4-Node Graph
Source node 0. Edges: (0-1, w=1), (0-2, w=0), (2-3, w=0), (2-1, w=0).
- Init:
dist[0]=0,deque=[0]. - Pop front 0: relax (0,2,w=0) →
dist[2]=0,push_front(2). Relax (0,1,w=1) →dist[1]=1,push_back(1). Deque:[2, 1]. - Pop front 2: relax (2,3,w=0) →
dist[3]=0,push_front(3). Relax (2,1,w=0) →dist[1]=0(improved!),push_front(1). Deque:[1, 3, 1]. - Pop front 1 (dist=0): node 1 final distance is 0!
Complexity Analysis
| Algorithm | Time Complexity | Space Complexity | Primary Requirement |
|---|---|---|---|
| 0-1 BFS | $O(V + E)$ | $O(V)$ | Edge weights $\in \{0, W\}$ |
| Bidirectional BFS | $O(b^{d/2})$ | $O(b^{d/2})$ | Unweighted graph + known Target $T$ |
| Bidirectional Dijkstra | $O(E \log V)$ (much smaller constant) | $O(V)$ | Non-negative weights + known Target $T$ |
Implementations
Real-World Applications
Social Network Degree of Separation & Teleportation Grids
Finding the shortest connection path between two individuals on LinkedIn or Facebook uses **Bidirectional BFS**. Instead of searching millions of profiles in a 6-degree forward ball, searching simultaneously from both profiles intersects in a tiny fraction of the time. In game development, grid movement with zero-cost teleportation/warp gates relies on **0-1 BFS** to calculate optimal paths in $O(\text{Grid Size})$.
Exercises
- Prove that 0-1 BFS maintains a non-decreasing queue of distances.
- Extend 0-1 BFS to handle edge weights $\{0, A, B\}$. Under what conditions does a deque suffice?
- Why does Bidirectional Search require knowing the target node $T$ in advance?
- Challenge: Write a Bidirectional A* Search algorithm combining landmark heuristics with forward and backward searches.
Limitations
Target Requirement & Weight Bounds
0-1 BFS cannot be applied when edge weights take on arbitrary integer values (use Dial's or Dijkstra's algorithm instead). Bidirectional search is single-pair only (source to target) and cannot be used for single-source all-destination queries.