多源最短路问题,在默认边权相等的情况下,可以把Dijkstra算法默认用bfs写。
因为在bfs的队列中 只会有两种数值,x和x+1
一开始 默认源点是x,每遍历一个x的周围四个位置,就将其加入到队列中,加入后的是x+1
当x全部被pop出去之后 才会遍历x+1 接而出现x+2 (两段性)
因为存在两段性 所以队列里面是单调递增的
前面的值 在入队的时候 就已经确定此位置的最小值。
所以 当入队数达到n*m的时候 所有点的最小值就都求出来了 不用全部出队
先将多个起点加入队列 因为自己到自己的距离都是0 所以没有先后顺序
之后 遍历这些点周边的点 入队
ans是记录一共有多少元素入队
C++ 代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int N = 1002 , M = N*N;
typedef pair<int , int> PII;
int n,m;
int arr[N][N];
queue<PII> q;
int ans = 0;
void bfs()
{
int X[4] = {0,1,0,-1};
int Y[4] = {1,0,-1,0};
while(!q.empty()){
PII top = q.front();q.pop();
for(int i = 0; i < 4; i ++ )
{
int xx = X[i]+top.first;
int yy = Y[i]+top.second;
if(xx<1 ||yy<1|| xx>n || yy>m )continue;
if(arr[xx][yy]==-1){
arr[xx][yy] = arr[top.first][top.second]+1;
ans++;
q.push({xx,yy});
if(ans==n*m)return;
}
}
}
return;
}
int main()
{
memset(arr, -1 , sizeof arr);
cin>>n>>m;
for(int i = 1; i <= n; i ++ )
for(int j = 1; j <= m; j ++ )
{
int temp;
scanf("%1d",&temp);
if(temp==1){
q.push({i,j});
arr[i][j] = 0;
ans++;
}
}
bfs();
for(int i = 1; i <= n; i ++ ){
for(int j = 1; j <= m; j ++ )
{
printf("%d ",arr[i][j]);
}
printf("\n");
}
return 0;
}