A Bit of History
Multi-source BFS is a direct extension of Edward F. Moore's 1959 breadth-first search — the innovation is not a new traversal rule but a new way of thinking about the "start" of the search. The technique became especially popular through competitive programming communities in the 2000s and 2010s as a standard pattern for "nearest facility" style problems, and is formally equivalent to adding a single virtual super-source vertex connected to every real source with zero-weight edges — a trick with roots in classical network-flow reductions (Ford & Fulkerson, 1956) where multiple sources/sinks are similarly unified into one.
Working Principle: The Virtual Super-Source
Rather than running $k$ separate BFS traversals (one per source) and taking a pointwise minimum — costing $O(k \cdot (V + E))$ — multi-source BFS achieves the same result in a single $O(V + E)$ pass:
- Initialize the BFS queue with all source vertices simultaneously, each with distance 0.
- Proceed with standard BFS exactly as usual — pop from the front, relax unvisited neighbors, push to the back.
- Because every source starts at distance 0 and BFS explores level-by-level, the first time any vertex $v$ is reached, it's reached via the closest source — exactly the value we want.
Why This Works: The Super-Source Equivalence
This is mathematically identical to adding one new virtual vertex $s^*$ connected by zero-weight edges to every real source, then running ordinary single-source BFS from $s^*$. Since $s^*$'s neighbors all start at distance 1 from $s^*$ (i.e., distance 0 from themselves after subtracting the phantom hop ), seeding the queue directly with all sources at distance 0 is exactly equivalent — just without materializing the extra vertex.
Worked Example
The classic "Rotten Oranges" grid problem: cells are 0 (empty), 1 (fresh orange), or 2 (rotten orange). Each minute, every rotten orange rots its fresh neighbors. Find the minimum time for all oranges to rot, or -1 if impossible.
- Seed the BFS queue with every initially-rotten cell (multiple sources), each tagged with time 0.
- Process level-by-level: at each BFS "layer," every fresh neighbor of a rotten cell becomes rotten, tagged with time = current level + 1.
- The answer is the maximum time value assigned to any cell — the moment the "wave" of rot from all initial sources finally reaches the farthest fresh orange.
- If any fresh orange (1) remains unvisited after BFS completes, the answer is -1 (unreachable pocket).
Complexity Analysis
$$\text{Time: } O(V + E) \qquad \text{Space: } O(V)$$
This is exactly the same complexity as single-source BFS — the number of sources $k$ never appears in the asymptotic bound, since every vertex and edge is still visited at most once total across the entire multi-source frontier expansion.
Implementation
Real-World Applications
Nearest Facility Location & Wildfire Spread Simulation
Urban planning tools computing "distance to nearest fire station/hospital/school" across an entire city grid use multi-source BFS to answer the query for every location in one linear pass, rather than one BFS per facility. Wildfire and epidemic spread simulations model multiple simultaneous ignition/infection points the same way — the "rotten oranges" pattern generalizes directly to any multi-origin spreading phenomenon on a grid or graph.
Exercises
- Solve the "Rotten Oranges" problem on a 5x5 grid with 3 initially-rotten cells scattered around the border.
- Prove formally that multi-source BFS produces the same result as running single-source BFS from each source and taking the pointwise minimum.
- Extend multi-source BFS to also record which source is nearest to each vertex (not just the distance).
- Challenge: Adapt the technique to weighted graphs using a multi-source Dijkstra (seed the priority queue with all sources at distance 0 instead of the plain queue).
Limitations
Unweighted Graphs Only (in Its Basic Form)
The plain queue-based version only produces correct nearest-source distances on unweighted graphs (or grids where every move costs the same). For weighted graphs, the queue must be replaced with a priority queue seeded with all sources — effectively a multi-source Dijkstra — otherwise a vertex might be finalized via a longer unweighted hop-count path before a shorter weighted path is discovered.