题目大意:
小希设置了一个图,希望任意两个顶点仅有一条路径相通。
题目测试数据与数据范围:
6 8 5 3 5 2 6 45 6 0 08 1 7 3 6 2 8 9 7 57 4 7 8 7 6 0 03 8 6 8 6 45 3 5 6 5 2 0 0-1 -1
Yes Yes No
对于第一,二个图符合设计要求,而第三个图去到达5,或者8都有两条路径,所以不符合要求。房间的编号为至少 1,最大为 100000.
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1272
题目分折:
首先题目要求在她给出的图中,任何两个顶点有且只有一条路径,那么只能是一个连通图,而且不能有环。对于环的判定最先想到的是并查集当两个顶点都已经在一个集合之中,再加入这条边的话,肯定会出现环。所以整个思路就是在输入顶点时,记录最小最大值,并标记出现的顶点。若在输入过程中,并查过程中,没有出现环,还得检查这个图是否只是一个连通图,否则输出NO。
小乐一下:
并查集的主要有两个操作,一个合并两个集合,第二个查找自己的祖先(在查找的过程中就可以进行路径压缩),而启发式合并一般不用,用了作用并不是很明显。
代码,更好更简洁的由你来实现,不要直接复制。
#include<stdio.h>
#include<string.h>
int father[100010];
int mark[100010];
int finds(int x){
return x==father[x]?x:father[x]=finds(father[x]);
}
void bing(int a,int b){
father[a] = b;
}
int main(){
int a,b;
int flag = 0;
int mins,maxs;
int counts,i,aa,bb;
while(scanf("%d%d",&a,&b)!=EOF){
if(a==-1 && b==-1) break;
if(a==0 && b==0){
printf("Yes\n");
continue;
}
flag = 0;
for(i = 1;i<100010;i++) father[i] = i;
memset(mark,0,sizeof(mark));
maxs = -1;
mins = 99999999;
while(a||b){
if(a>maxs) maxs = a;
if(b>maxs) maxs = b;
if(a<mins) mins = a;
if(b<mins) mins = b;
mark[a] = mark[b] = 1;
aa = finds(a);
bb = finds(b);
if(aa==bb) flag = 1;
else bing(aa,bb);
scanf("%d%d",&a,&b);
}
if(flag) {printf("No\n");continue;}
counts = 0;
for(i = mins ;i<=maxs;i++){
if(mark[i] && father[i]==i)counts++;
}
if(counts == 1) printf("Yes\n");
else printf("No\n");
}
return 0;
}
伟大的梦想成就伟大的人,做好细节,做好点点滴滴,做好认真。