zoj1268-简单并查集(判断是否为一颗树)

/*
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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值