2Brute2Best
🔥0
02

Multi-source BFS (Graph BFS / DFS Sub-pattern)

Many cells spread at the same speed; find each cell's distance to the nearest source (or when the spread ends).

Signals in the problem statement
  • ›

    "every minute, each … spreads to its neighbours"

  • ›

    "distance to the nearest 0 / gate / water"

  • ›

    "minimum time until all …"

What makes it different

Rotting Oranges is the template: all rotten oranges start in the queue, and one BFS level is one minute; any fresh orange left at the end means -1. 01 Matrix and Walls and Gates start from the targets (the 0s, the gates), not from the cells asking the question. Map of Highest Peak is the same BFS with water as the sources; the distance is the height.

Questions

ordered from “learn the idea” to “recognise it without help”
  1. 1
    Rotting Oranges
    Basic Anchor·LeetCode #994
    Medium
  2. 2
    01 Matrix
    Basic Reinforcement·LeetCode #542
    Medium
  3. 3
    Walls and Gates
    Slight Variation·LeetCode #286 Premium
    Medium
  4. 4
    Map of Highest Peak
    Medium·LeetCode #1765
    Medium

Template

multi-source-bfs-template.cpp
// Multi-source BFS: every source goes in the queue at distance 0, then all spread together.
vector<vector<int>> nearestSource(const vector<vector<int>>& grid) {   // 1 = source, 0 = open, -1 = wall
    int R = grid.size(), C = grid[0].size();
    vector<vector<int>> dist(R, vector<int>(C, -1));                     // -1 = not reached yet
    queue<pair<int, int>> q;
    for (int r = 0; r < R; r++)
        for (int c = 0; c < C; c++)
            if (grid[r][c] == 1) { dist[r][c] = 0; q.push({r, c}); }
    int dr[4] = {1, -1, 0, 0}, dc[4] = {0, 0, 1, -1};
    while (!q.empty()) {
        auto [r, c] = q.front(); q.pop();
        for (int d = 0; d < 4; d++) {
            int nr = r + dr[d], nc = c + dc[d];
            if (nr < 0 || nc < 0 || nr >= R || nc >= C || grid[nr][nc] == -1 || dist[nr][nc] != -1) continue;
            dist[nr][nc] = dist[r][c] + 1;        // first time reached = nearest source
            q.push({nr, nc});
        }
    }
    return dist;
}
Remember this · Graph BFS / DFS
Trigger
Grid of cells, islands, regions, "minimum steps", transformations between states, connected components.
Think
What is a node, what is an edge, and do I need the shortest path or just reachability?
Key question
How do I mark visited so I never process a node twice?