【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:
K B1 B2​ … BK
where K is the number of birds in this picture, and B​i’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 104.

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.

翻译:每个输入文件包含一组测试数据。对于每组测试数据,第一行包括一个正整数N (≤10​4),代表图片上鸟的数量。接下来N行,每一行按照以下格式描述一幅画:
K B1 B2​ … BK
K为图像中鸟的数量,Bi表示鸟的编号。数据保证所有图片上的鸟被标记为从1到某个不大于104的数字。
在图片后是一个正整数Q (≤10​4) ,代表查询的数量。接下来Q行,每一行包括两个鸟的编号。

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.

翻译:对于每组测试数据,输出一行最多可能存在的树的棵数和鸟的数量。接下来对于每个查询,输出一行Yes如果两只鸟来自同一棵树,否则输出No。


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



解题思路

通过并查集解决,将同一张照片上出现的鸟合并。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<vector>
#include<algorithm>
#define INF 99999999
#define bug puts("Hello\n")
int N;
using namespace std;
int tree[10010];//并查集表示两只鸟是否在同一集合 
bool bird[10010];//判断该鸟是否存在 
void init(){
	for(int i=1;i<10010;i++){
		tree[i]=i;
		bird[i]=false;
	}
}
int find(int x){
	if(x==tree[x])return x;
	else return tree[x]=find(tree[x]);
}
void Union(int x,int y){
	int fx=find(x);
	int fy=find(y);
	if(fx!=fy)tree[fy]=fx;
} 
bool Judge(int a,int b){
	int fa=find(a);
	int fb=find(b);
	if(fa!=fb)return false;
	else return true;
}
int countTree(){
	int ccount=0;
	for(int i=1;i<=10010;i++){
		int tmp=find(i);
		if(i==tmp&&bird[i])ccount++;
	}
	return ccount;
}
int countBird(){
	int ccount=0;
	for(int i=1;i<=10010;i++){
		if(bird[i])ccount++;	
	}
	return ccount;
}
int main(){
	init();
	scanf("%d",&N);	
	for(int i=0;i<N;i++){
		int K,a,tmp;
		scanf("%d",&K);
		for(int k=0;k<K;k++){
			scanf("%d",&a);
			if(!bird[a])bird[a]=true;
			if(k==0)tmp=a;
			else Union(tmp,a);
		}
	}
	int Bird=countBird();
	int Tree=countTree();
	printf("%d %d\n",Tree,Bird);
	int Q;
	scanf("%d",&Q);
	int a,b;
	for(int i=0;i<Q;i++){
		scanf("%d %d",&a,&b);
		if(Judge(a,b))printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值