多源 BFS 概述
在图论和网格问题中,我们常遇到最短路径的求解。传统的单源最短路只有一个起点,而多源最短路则涉及多个起点同时向终点扩散。对于边权相同的场景(如网格中的上下左右移动),广度优先搜索(BFS)是解决此类问题的最优选择。
核心解法有两种思路:
- 暴力枚举:将多源问题转化为若干个单源问题,分别计算每个起点到目标的最短距离,取最小值。这种方法在数据量大时容易超时。
- 多源初始化:将所有起点视为一个整体,一次性放入队列进行层序遍历。这是更高效的标准做法。
下面通过四道经典题目来深入理解这一模式。
542. 01 矩阵
问题描述:给定一个由 0 和 1 组成的矩阵,计算每个元素到最近的 0 的距离。
思路分析
如果我们对每个 1 都单独运行一次 BFS 寻找最近的 0,时间复杂度会达到 O(MNM*N),在大数据量下必然超时。优化的关键在于利用多源 BFS 的特性。
我们可以先将所有值为 0 的位置加入队列,并将它们作为第一层。然后向外扩展,第一次访问到的 1 就是距离该 0 最近的位置。这样只需遍历一遍矩阵,时间复杂度降为 O(M*N)。
代码实现
import java.util.LinkedList;
import java.util.Queue;
class Solution {
int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
public int[][] updateMatrix(int[][] mat) {
int m = mat.length;
int n = mat[0].length;
int[][] ret = new int[m][n];
Queue<int[]> queue = new LinkedList<>();
// 初始化:所有 0 入队,距离设为 0;1 设为 -1 表示未访问
for (int i = ; i < m; i++) {
( ; j < n; j++) {
(mat[i][j] == ) {
queue.add( []{i, j});
ret[i][j] = ;
} {
ret[i][j] = -;
}
}
}
(!queue.isEmpty()) {
[] arr = queue.poll();
( ; i < ; i++) {
arr[] + dx[i];
arr[] + dy[i];
(x >= && x < m && y >= && y < n && ret[x][y] == -) {
ret[x][y] = ret[arr[]][arr[]] + ;
queue.add( []{x, y});
}
}
}
ret;
}
}


