二刷提高课,题解目录在这里— 提高课的题解目录
当我们读完题第一想就是以每个点作为起点求一下最短距离
但是很明显会超时,那该如何处理呢,有那么多起点
可以知道对于每个点我们求的并不是到其他所有点的最短距离,而是到1的最短距离
根据正难则反,也就是所有1到每个点最短的距离
当我们遇到多对一求最短路时,可以建立一个虚拟源点,
使得其对所有的起点到虚拟源点距离为零(核心思想需掌握)
求虚拟源点对目标点的最短路便和求这几条最短路目标相同,便可以求出最短的
而这题是多对多,那么我们通过虚拟源点将其转化为一对多
一对多比较简单,用bfs遍历一遍即可保证均为最短距离了
而虚拟源点其实我们无需将其真的表现出来(只需要将所有为1的入队即可)
用这些点来遍历到所有便可以求出所有点到1的最短距离
#include<iostream>
#include<cstring>
using namespace std;
typedef pair<int ,int >PII;
const int N=1100;
PII q[N* N];
int dist[N][N];
char g[N][N];
int n,m;
int dx[4]={1,0,0,-1};
int dy[4]={0,1,-1,0};
int bfs()
{
int hh=0,tt=-1;
memset(dist,-1,sizeof dist);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(g[i][j]=='1')
{
dist[i][j]=0;
q[++tt]={i,j};
}
}
while(hh<=tt)
{
auto t=q[hh++];
for(int i=0;i<4;i++)
{
int a=t.first+dx[i],b=t.second+dy[i];
if(a>n||a<=0||b>m||b<=0)continue;
if(dist[a][b]!=-1)continue;
dist[a][b]=dist[t.first][t.second]+1;
q[++tt]={a,b};
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>g[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;
}