7-2 看照片找基友 (20分)

7-2 看照片找基友 (20分)— 并查集

小A是个单身狗,他有很多好基友,他们平时喜欢出去聚会和旅游,每次聚会都会照一张集体照上传到群共享,有一天,小A整理照片,想通过照片来看看他们这群基友的情况。我们假定,在同一张照片里同时出现的,两两之间都是好基友,基友的基友也是好基友。那么问题来了,你能帮小A确定任意的两个人是否好基友吗?

输入格式:

首先输入照片的张数N(N<10000),之后N行,按以下格式输入照片里的情况:

K P1 P2 P3 …… PK
其中K是照片中的人数,后面的K个数是照片中人的编号,我们假定从1开始连续编号,人数不超过10000。 接下来输出查询的个数T(T<10000),之后T行,每行输入两个数,分别是查询的两个人的编号。

输出格式:

首先输出基友圈的个数和所有人数,之后对T组查询,在一行中输出查询结果,如果两个是好基友,输出Yes,否则输出No。

输入样例:

在这里给出一组输入。例如:

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

输出样例:

在这里给出相应的输出。例如:

3 12
No
Yes

作者
胡伟平
单位
广西科技大学
代码长度限制
16 KB
时间限制
150 ms
内存限制

笔记:这道题主要考并查集,整体上不难。但是我一共交了不下二十次(就差颁发最佳拼搏奖了@-@),一直卡在最后一个测试点,检查代码也没看出来哪错了(崩溃边缘徘徊)。最后重新理解了一下题目,发现我将人数主观理解了,题目明确讲到 “我们假定从1开始连续编号,人数不超过10000。”,我直接将它设定为我们输入的人数。

这个道题深刻的告诉我一定要 认真看题,切勿主观认为

正确代码:

#include
#include
#include
#include
using namespace std;
int count,ans=0;
int s[20005];
void init(){
	for(int i=0;i<10005;i++){
		s[i]=i;
	}
}
int find(int x){
	if(s[x]==x){
		return x;
	}
	else{
		s[x]=find(s[x]);
		return s[x];
	}
}
int merge(int a,int b){
	int a1=find(a);
	int b1=find(b);
	if(a1!=b1){
		s[a1]=b1;
		ans++;
	}
}
int main(){
	int t,n,k;
	while(cin>>n){
		ans=0;
		count=0;
		int a,b;
		map<int,int>mp;
		init();
		while(n--){
			cin>>k;
			for(int i=0;i<k;i++){
				cin>>b;
				if(i==0){
					a=b;
				}
				if(b>count) count = b;//看清题目, 后面的K个数是照片中人的编号
					merge(a,b);	//	我们假定从1开始连续编号,人数不超过10000
				
			}
		}
		cin>>t;
		ans=count-ans;
		if(mp[1]==0) count+1;
		cout<<ans<<" "<<count<<endl;
		while(t--){
			cin>>a>>b;
			if(find(a)==find(b)){
				cout<<"Yes"<<endl;
			}
			else{
				cout<<"No"<<endl;
			}
		}
	}
	return 0;
}
*/

你可能感兴趣的:(#,并查集,算法)