pat 1118 Birds in Forest (25分) 并查集

Some scientists took pictures of thousands of birds in a forest. Assume that all the birds appear in the same picture belong to the same tree. You are supposed to help the scientists to count the maximum number of trees in the forest, and for any pair of birds, tell if they are on the same tree.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive number N (≤10^4) which is the number of pictures. Then N lines follow, each describes a picture in the format:

B1​​ B2​​ ... BK​​

where K is the number of birds in this picture, and Bi​​'s are the indices of birds. It is guaranteed that the birds in all the pictures are numbered continuously from 1 to some number that is no more than 1.

After the pictures there is a positive number Q (≤10^4) which is the number of queries. Then Q lines follow, each contains the indices of two birds.

Output Specification:

For each test case, first output in a line the maximum possible number of trees and the number of birds. Then for each query, print in a line Yes if the two birds belong to the same tree, or No if not.

Sample Input:

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

Sample Output:

2 10
Yes
No
 
 
题目描述:
第一行输入n组数据,每一组数据表示这些鸟在同一颗树上。最后输出,有几棵树,和鸟的数量。
再判断给一对鸟,是不是在同一颗树上,是输出Yes,不在同一颗树上输出No
 
 
解题思路:
这道题是典型的并查集题目,这里要注意一点是是,每次找节点的父节点时,应该直接把这个节点的父节点更新为最顶上的父节点,避免重复寻找例如3 -> 5 -> 6 ->8 更新完就变为  3->8, 5->8  6->8,
要不然会有个测试用例会超时
int find(int x){  //递归寻找每个节点的根节点 
	if(x == father[x]){
		return x;
	}
	return find(father[x]);    //不更新路径  
}

不超时应该  return father[x] = find(father[x])

正确的代码如下: 

#include<cstdio>
#include<cstdlib>
#include<set>
#include<vector>
#include<algorithm>

using namespace std;

const int maxn = 10009; //题目要求10^4 
int father[maxn];    //存放每个下标的父节点下标,根节点的父节点是自身 

int find(int x){  //递归寻找每个节点的根节点 
	if(x == father[x]){
		return x;
	}
	return father[x] = find(father[x]);
}

void Union(int x,int y){  //合并两个节点 
	int fx = find(x);
	int fy = find(y);
	
	if(fx != fy){
		father[fx] = fy;
	}
}

int main(){
	
	int n,k,a,b;
	
	int max = 0; //鸟的数量是最大的下标 
	
//	freopen("C:\Users\zzloyxt\Desktop\1.txt","r",stdin);	
	scanf("%d",&n);
	for(int i=1;i<maxn;i++){
		father[i] = i; // 初始化数组,节点自己的father是自己 
	}
	
	for(int i=1;i<=n;i++){
		scanf("%d",&k); // 输入有k 只鸟 
		scanf("%d",&a); //输入第一只鸟 
		if(a>max){
			max = a;
		}
		for(int j=1;j<k;j++){  // 输入剩余的k-1只 
			scanf("%d",&b);
			if(b>max){
				max = b;
			}
			Union(a,b);
		}
		
	}	
	
	//输出鸟的数量和树的数量,因为下标是从1-m所以鸟的数量就是最大的m 	
	int count = 0;
	
	for(int i=1;i<=max;i++){
		if(find(i) == i){
			count++;
		}
	}
	
	
	printf("%d %d
",count,max);
	scanf("%d",&k);
	for(int i=0;i<k;i++){
		scanf("%d %d",&a,&b);
		
		if(find(a) == find(b)){
			printf("Yes
");
		}else{
			printf("No
");
		}
	}
	
	return 0;
}
 
 
 
 
原文地址:https://www.cnblogs.com/zzlback/p/12409035.html