题目描述
巨噬细胞需要打扫身体里的病原体和细胞残片,现在身体中有n个房间(编号为1~N),巨噬细胞在其中编号为k的房间刚刚打扫结束。房间之间有一些道路供巨噬细胞移动,请问巨噬细胞到其他的细胞最少要经过多少个房间呢?
输入格式:
输入包括两行,第一行为两个整数n,k,m,分别表示房间的个数、巨噬细胞所在的房间、以及道路的条数。
接下来m行每行包括三个整数uu,vv分别表示,分别表示每条道路的起点和终点。
输出格式:
输出包括一行,包括n个空格隔开的整数,分别表示到每一个房间最少路过的房间数,如果某个房间无法到达,那个房间对应位置输出-1。
输入样例#1:
10 3 12
1 2
2 3
3 4
3 7
4 7
7 9
9 10
4 8
4 5
1 5
1 6
6 5
输出样例#1:
1 0 0 0 1 2 0 1 1 2
说明
输出为要经过的房间的数量,不包括起点房间和终点房间,每条道路都是双向的。
1<=n<=1000
1<=m<=n*n
代码及注释
//直接搬题解上的代码。
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f
#define maxn 1005 //定义常量。
int n,k,m;
int res[maxn];
int arr[maxn][maxn];
bool book[maxn];
void mmp() //自定义初始化函数,初始化三个数组。
{
for(int i=0;i<maxn;i++)
for(int j=0;j<maxn;j++)
{
if(i==j)
arr[i][j]=0;
else
arr[i][j]=INF;
}
memset(res,INF,sizeof(res));
memset(book,false,sizeof(book));
}
int main()
{
cin>>n>>k>>m;
mmp();
int x,y;
for(int i=0;i<m;i++)
{
cin>>x>>y;
arr[x][y]=1; //从x到y的路线数为1。
arr[y][x]=1; //每条道路是双向的。
}
queue<int>q; //定义一个队列q。
q.push(k); //从巨噬细胞所在房间开始循环。
book[k]=true; //标记。
res[k]=0; //k到k的路为0。
while(!q.empty())
{
int now=q.front(); //返回队列首元素。
q.pop(); //删除队列首元素。
book[now]=false; //标记。
for(int i=1;i<=n;i++)
{
if(res[i]>res[now]+arr[now][i]) //寻找能从第now个房间直接到达的房间。
{
res[i]=res[now]+arr[now][i]; //记录从第k个房间到这个房间的最短路。
if(!book[i]) //确保扫过每个房间且每个房间只扫一次。
{
q.push(i);
book[i]=true;
}
}
}
}
for(int i=1;i<=n;i++)
{
if(res[i]>0)
res[i]--; //路过的房间数等于经过的路数-1。
}
for(int i=1;i<n;i++) 按照标准格式输出。
{
if(res[i]<INF)
cout<<res[i]<<" ";
else
cout<<-1<<" ";
}
if(res[n]<INF)
cout<<res[n];
else cout<<-1<<" ";
return 0;
}