试题描述
|
我们班共有n名同学,编号1至n。其中,有m对无话不说的好朋友。作为一对无话不说的好朋友,只要其中一个人知道了什么小秘密,就会立即告知另一个人。 现在,1号同学知道了一个小秘密,请问班上哪些同学会知道这个小秘密?此外,知道小秘密的同学分别都是通过几次消息传递知道这个秘密的? |
输入
|
第一行包含两个正整数n、m,分别表示同学数量和朋友对数。
随后m行,每行包含两个正整数,表示一对朋友。 |
输出
|
请输出n行,每行一个整数。对于第i行的整数,若i号同学知道这个秘密,请输出它是通过几次消息传递知道这个秘密的;若i号同学不知道这个秘密,请输出-1。
|
输入示例
|
6 5
1 2 2 3 3 1 3 4 4 5 |
输出示例
|
0
1 1 2 3 -1 |
其他说明
|
对于30%的数据,n<=100, m<=200;
对于60%的数据,n<=1000, m<=2000; 对于100%的数据,n<=100000, m<=200000。 |
思路:
1.初始化:①dis ②q
2.while(队列非空){
①s++=1(将队尾元素退出一个)
②找相邻点
若dis==-1 {(1)加入队列 (2)修改小s}
1 #include <iostream> 2 3 using namespace std; 4 struct Edge //结构体 5 { 6 int x,y,next; 7 }map[401010]; //由于是无向图,所以范围要 ×2 8 9 int head[101010]; 10 11 void add_edge(int i,int x,int y) 12 { 13 map[i].x=x; 14 map[i].y=y; 15 map[i].next=head[x]; 16 head[x]=i; 17 } 18 19 int dis[201010],q[201010],st,ed; //dis是每个顶点的距离,也是最后答案;q是队列;st=start,ed=end 20 21 int main() 22 { 23 int n,m; 24 scanf("%d%d",&n,&m); 25 for(int i=1;i<=n;i++) head[i]=-1; //全部初始化为-1,方便后面找终点 26 for(int i=0;i<m;i++) 27 { 28 int x,y; 29 scanf("%d%d",&x,&y); 30 add_edge(2*i,x,y); //如果只写一个,建的是有向图 31 add_edge(2*i+1,y,x); //为了不让后面的覆盖前面的,i的位置不能相同 32 } 33 //以下是初始化-------------------------- 34 for(int i=1;i<=n;i++) dis[i]=-1; 35 dis[1]=0; 36 st=ed=0; //队列清空(初始化) 37 q[ed++]=1; 38 //以上是初始化-------------------------- 39 while(st<ed) //队列非空 40 { 41 int now=q[st++]; //取出一个元素 42 for(int j=head[now];j!=-1;j=map[j].next) 43 { 44 if(dis[map[j].y]==-1) //这个人还不知道消息 45 { 46 q[ed++]=map[j].y; 47 dis[map[j].y]=dis[now]+1; 48 } 49 } 50 } 51 for(int i=1;i<=n;i++) printf("%d ",dis[i]); 52 //system("pause"); 53 return 0; 54 }