多源BFS
目录
多元最短路问题
利用BFS解决边权为1的多源最短路问题
解法一:暴力解法,将多源最短路问题转化为若干个单源最短路问题
解法二:把所有源点看成一个源点,转化为单一的单源最短路径问题

把所有的起点加入到队列,一层一层地往外进行扩展
试题1:矩阵

算法原理
解法一:一个位置一个位置求(O(N^3))
解法二:多元BFS + 正难则反
把所有的0当成起点,把所有的1当成终点
第一步:将所有的0坐标加入到队列
第二步:一层一层向外扩展
细节:
将distance初始化为-1,标记当前位置没有被搜索(类似:vis数组)
从distance中直接获取当前层数(类似:step,sz)

代码编写
cpp
class Solution
{
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
public:
vector<vector<int>> updateMatrix(vector<vector<int>>& mat)
{
int m = mat.size(), n = mat[0].size();
// dist[i][j] == -1: 没有搜索过
// dist[i][j] != -1: 最短距离
vector<vector<int>> dist(m, vector<int>(n, -1));
queue<pair<int, int>> q;
// 1. 把所有源点加入队列
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
if(mat[i][j] == 0)
{
q.push({i, j});
dist[i][j] = 0;
}
}
}
// 2. 一层一层往外扩展
while(q.size())
{
auto [a, b] = q.front();
q.pop();
for(int i = 0; i < 4; i++)
{
int x = a + dx[i];
int y = b + dy[i];
if(x >= 0 && x < m && y >= 0 && y < n && dist[x][y] == -1)
{
dist[x][y] = dist[a][b] + 1;
q.push({x, y});
}
}
}
return dist;
}
};
试题2:飞地的数量

算法原理
解法一:一个一个判断
解法二:正难则反
从边界上的1往内部搜索

代码编写
cpp
class Solution
{
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
public:
int numEnclaves(vector<vector<int>>& grid)
{
int m = grid.size(), n = grid[0].size();
vector<vector<bool>> vis(m, vector<bool>(n));
queue<pair<int, int>> q;
// 1. 把边上的1加入到队列
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
if(i == 0 || i == m - 1 || j == 0 || j == n - 1)
{
if(grid[i][j] == 1)
{
q.push({i, j});
vis[i][j] = true;
}
}
}
}
// 2. 多源BFS
while(q.size())
{
auto [a, b] = q.front();
q.pop();
for(int i = 0; i < 4; i++)
{
int x = a + dx[i];
int y = b + dy[i];
if(x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1 && !vis[x][y])
{
q.push({x, y});
vis[x][y] = true;
}
}
}
// 3. 统计结果
int ret = 0;
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
if(grid[i][j] == 1 && !vis[i][j])
{
ret++;
}
}
}
return ret;
}
};
试题3:地图中的最高点

算法原理
解法:多源BFS

代码编写
cpp
class Solution
{
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
public:
vector<vector<int>> highestPeak(vector<vector<int>>& isWater)
{
int m = isWater.size(), n = isWater[0].size();
vector<vector<int>> dist(m, vector<int>(n, -1));
queue<pair<int, int>> q;
// 1. 把所有源点入队列
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
if(isWater[i][j])
{
dist[i][j] = 0;
q.push({i, j});
}
}
}
// 2. 多源BFS
while(q.size())
{
auto [a, b] = q.front();
q.pop();
for(int i = 0; i < 4; i++)
{
int x = a + dx[i];
int y = b + dy[i];
if(x >= 0 && x < m && y >= 0 && y < n && dist[x][y] == -1)
{
dist[x][y] = dist[a][b] + 1;
q.push({x, y});
}
}
}
return dist;
}
};
试题4:地图分析

算法原理

代码编写
cpp
class Solution
{
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
public:
int maxDistance(vector<vector<int>>& grid)
{
int m = grid.size(), n = grid[0].size();
vector<vector<int>> dist(m, vector<int>(n, -1));
queue<pair<int, int>> q;
// 1. 所有源点入队列
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
if(grid[i][j])
{
dist[i][j] = 0;
q.push({i, j});
}
}
}
// 2. 多源BFS
int ret = -1;
while(q.size())
{
auto [a, b] = q.front();
q.pop();
for(int i = 0; i < 4; i++)
{
int x = a + dx[i];
int y = b + dy[i];
if(x >= 0 && x < m && y >= 0 && y < n && dist[x][y] == -1)
{
dist[x][y] = dist[a][b] + 1;
q.push({x, y});
ret = max(ret, dist[x][y]);
}
}
}
return ret;
}
};