hdu1272---------------------并查集 + 判联通
这道题给出了一些点和边的信息,让你判断是否能够组成一个无环的联通集合,且这个唯一的集合可以为空。
你需要做:1,判是否成环, 只要输入的边的两个点有共同的父节点,那么着两个点就成环了。
2,判联通, 只要最后判断根节点的总数为1即可。
这道题花了我一上午,WA了5次。
前两次是我不知道判联通,该! 后几次是太粗心了,初始化该写100000,却写成了10000! 累死我了,怎么也找不出原因!唉,悲剧啊
注意若只输入0 0,则输出Yes
AC代码:
#include<stdio.h>
int set[100005];
int flag[100005];
int temp;
int find(int x)
{
int r;
r=x;
while(set[r]!=r)
r=set[r];
return r;
}
void merge(int x,int y)
{
int fx,fy;
fx=find(x);
fy=find(y);
if(fx==fy) //表示有环
temp=0;
if(fx!=fy)
{
if(fx<fy)
set[fy]=fx;
else
set[fx]=fy;
}
}
int main()
{
int i,j,count;
int x,y;
while(scanf("%d%d",&x,&y)!=EOF&&x!=-1)
{
if(x==0)
{
printf("Yes\n");
continue;
}
for(i=1;i<=100001;i++)
{
flag[i]=0;
set[i]=i;
}
temp=1; //初始化,表示可以
flag[x]=1; //表示这个点被访问过
flag[y]=1;
merge(x,y);
while(scanf("%d%d",&x,&y)!=EOF&&x!=0)
{
merge(x,y);
flag[x]=1;
flag[y]=1;
}
count=0;
for(i=1;i<=100001;i++)
{
if(flag[i]&&set[i]==i)
count++;
}
if(count>1) //判联通,若这些点是一个集合,则根节点只有一个
temp=0;
if(temp==1)
printf("Yes\n");
if(temp==0)
printf("No\n");
}
return 0;
}