单源最短路问题 vs 多源最短路问题
- 当问题中只存在一个起点时,这时的最短路问题就是单源最短路问题。
- 当问题中存在多个起点而不是单一起点时,这时的最短路问题就是多源最短路问题。
想知道从这个点出发,到达终点,最短路径是多少。这是单源最短路。

但如果我的出发点有多个时,是多源最短路问题。

多源BFS:多源最短路问题的边权都为 1时,此时就可以用多源BFS来解决。
把这些源点汇聚在一起,等效成一个"超级源点",然后从这个"超级源点"开始,处理最短路问题。落实到代码上时:
- 初始化的时候,把所有的源点都加入到队列里面;
- 然后正常执行bfs的逻辑即可。

- 曼哈顿距离:两个坐标:横坐标差的绝对值+纵坐标差的绝对值。
- 正难则反,正着求比较难解的话,可以反着来求。
题目:矩阵距离
求每个0到1,最短要走几步
思路:我们可以把所有的1点,push进队列,然后每层向外走一步,并且同步记录步数。第一个遇到的点记录的肯定是最短路径。如果已经记录了最短路径,就continue。

cpp
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
int n, m;
const int N = 1010;
char a[N][N];
int dist[N][N];
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
typedef pair<int, int> PII;
void bfs()
{
queue<PII> q;
memset(dist, -1, sizeof(dist));
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if (a[i][j] == '1')
{
q.push({i, j});
dist[i][j] = 0;
}
}
}
while(q.size())
{
auto t = q.front(); q.pop();
int x1 = t.first, y1 = t.second;
for (int i = 0; i < 4; i++)
{
int x2 = x1 + dx[i], y2 = y1 + dy[i];
if (x2 < 1 || x2 > n || y2 < 1 || y2 > m || dist[x2][y2] != -1) continue;
dist[x2][y2] = dist[x1][y1] + 1;
q.push({x2, y2});
}
}
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> a[i][j];
}
}
bfs();
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cout << dist[i][j] << " ";
}
cout << endl;
}
return 0;
}