/*
zoj1268
【题目大意】
判断是否是一颗树。
分析:
1.不能出现环,否则是图。
2.只有一颗树(所有结点组成一颗树,边数为n-1) 。
*/
#include <stdio.h>
#include <string.h>
int pre[100010];
int rank[100010];
struct pt
{
int x,y;
}P[100010];
int k;
int min(int a,int b){return a>b?b:a;}
int max(int a,int b){return a>b?a:b;}
int edge,node;//边数,结点数
int ans;
void initialize()
{
ans=0;
memset(rank,0,sizeof(rank));
for(int i=0;i<100010;++i)
pre[i]=i;
edge=0;
node=0;
k=0;
}
int find(int x)
{
//查找根节点
int r=x;
while (pre[r]!=r)
r=pre[r];
//路径压缩
int i=x;
int j;
while(i!=r)
{
j=pre[i];
pre[i]=r;
i=j;
}
//返回根节点
return r;
}
int join(int x,int y)
{
int fx=find(x),fy=find(y);
if(fx!=fy)
{
pre[fx]=fy;
edge++;
return 0;
}
else
{ /*没事有做了一遍,这个fa,fy应该为x,y才对!不知道为什么这个能ac。貌似杭电也有一道这样的题目,数据都有问题啊!!!*/
int t1=min(fx,fy);
int t2=max(fx,fy);
for(int i=0;i<k;i++)
{
if(P[i].x==t1 && P[i].y==t2)
return 0;//已经存在的边
}
return 1;//成环
}
}
int main()
{
int a,b;
int i,j;
int iCase=1;
initialize();
while(scanf("%d%d",&a,&b) && !(a==-1&&b==-1))
{
if(a==0 && b==0)
{
printf("Case %d ",iCase++);
if(ans)//成环
printf("is not a tree.\n");
else
{
if((node-1 == edge) || (node==0 && edge==0))//边为n-1
printf("is a tree.\n");
else
printf("is not a tree.\n");
}
initialize();
}
else
{
ans+=join(a,b);
if(a>b)
{
P[k].x=b;
P[k++].y=a;
}
else
{
P[k].x=a;
P[k++].y=b;
}
if(!rank[a])node++;
if(!rank[b])node++;
rank[a]=b;
rank[b]=a;
}
}
return 0;
}
zoj1268-简单并查集(判断是否为一颗树)
最新推荐文章于 2021-01-11 19:32:26 发布