poj 1308 并查集(判断一组点对是否能够组成树)

题意:给定一组有序点对,如(a,b)表示有边从a指向b。问这组点对是否能够形成树。

思路:如果输入有(a,b),如果b没有其他前驱而且a不为b的前驱(或者a与b相等),则合并a和b,注意合并方向。对所有出现的点进行标记,最后通过father[i] = i的个数判断是树还是森林。

#include <stdio.h>
#include <string.h>
#define N 105
int T=1,a,b;
int father[N],num[N];
void init(){
	int i;
	memset(num,0,sizeof(num));
	for(i = 1;i<N;i++)
		father[i] = i;
}
int find(x){
	if(father[x] == x)
		return x;
	return father[x] = find(father[x]);
}
void merge(int x,int y){
	father[y] = find(x);
}
int main(){
	freopen("a.txt","r",stdin);
	while(scanf("%d %d",&a,&b) && !(a==-1&&b==-1)){
		int flag = 1,i,j,sum;
		if(!a && !b){
			printf("Case %d is a tree.\n",T++);
			continue;
		}
		init();
		do{
			num[b] = num[a] = 1;
			if(find(a)!=find(b) && father[b] == b)
				merge(a,b);
			else
				flag = 0;
		}while(scanf("%d %d",&a,&b) &&a&&b);
		if(flag)	
			for(i = 1,sum=0;flag&&i<N;i++){
				if(num[i] && father[i]==i)
					sum++;
				if(sum > 1)
					flag=0;
			}
		if(!sum)
			flag = 0;
		if(flag)
			printf("Case %d is a tree.\n",T++);	
		else
			printf("Case %d is not a tree.\n",T++);	
	}
	return 0;
}


你可能感兴趣的:(poj 1308 并查集(判断一组点对是否能够组成树))