并查集 hdu1325/poj1308 Is It A Tree?

题目描述
给几个结点集合,判断其是否满足树的定义
Alt
这个图结合样例看
Input

输入包含多组数据,每组数据是一个以0 0结尾的整数对列表,表示了一条通道连接的两个房间的编号。房间的编号至少为1,且不超过100000。每两组数据之间有一个空行。
整个文件以两个-1结尾。

Output

看样例

sample input

6 8  5 3  5 2  6 4
5 6  0 0

8 1  7 3  6 2  8 9  7 5
7 4  7 8  7 6  0 0

3 8  6 8  6 4
5 3  5 6  5 2  0 0
-1 -1

sample output

Case 1 is a tree.
Case 2 is a tree.
Case 3 is not a tree.

思路

注意树的三个注意点就好
1、结合第一个样例和第一个图,是由前一个数指向后一个数,后一个数是前一个数的子结点,前一个数是后一个数的父结点。如果存在x,y;find(y)不是y本身,就说明y已经是一个数的子结点了
2、输入的x和y如果是同一个父结点,那么把他们连起来就不是数了
3、还有就是注意根只能有一个。
接下来贴代码,上面也有一些注解

#include<cstdio>
using namespace std;

const int N=100010;
int f[N];       //f[i]表示i的父结点
bool v[N],flag;

void init() {         //初始化
	for(int i=1; i<N; i++ ) f[i]=i,v[i]=0;
	flag=1;
}

int find(int x) {        //路径压缩
	return x==f[x]?x:f[x]=find(f[x]);
}

void unions(int x, int y) {
	int fx=find(x);
	int fy=find(y);
	if ( fx==fy || y!=fy ) flag=0;  //fx=fy,对应注意点2;y=fy,对应注意点1
	if ( fx!=fy ) f[fy]=fx;   //注意一定是这样,y是x的子结点。
}

int main() {
	int x,y,kase=0;
	init();
	while(~scanf("%d %d",&x,&y) && x>=0 && y>=0 ) {
		if ( x==0 && y==0 ) {
			int root=0;
			for(int i=1; i<N; i++ ) {         //计算根的个数
				if ( v[i] && i==find(i) ) root++;
				if ( root>1 ) {
					flag=0;break;
				} 
			}
			if ( flag ) printf("Case %d is a tree.\n",++kase);
			else printf("Case %d is not a tree.\n",++kase);
			init();
			continue;
		}
		v[x]=v[y]=1;
		unions(x,y);
	}
	return 0;
}
发布了13 篇原创文章 · 获赞 6 · 访问量 582

猜你喜欢

转载自blog.csdn.net/zx1020354953/article/details/104103372