【PAT刷题甲级】1107.Social Clusters & 1118.Birds in Forest

1107 Social Clusters (30 分)

When register on a social network, you are always asked to specify your hobbies in order to find some potential friends with the same hobbies. A social cluster is a set of people who have some of their hobbies in common. You are supposed to find all the clusters.

Input Specification

Each input file contains one test case. For each test case, the first line contains a positive integer N (≤1000), the total number of people in a social network. Hence the people are numbered from 1 to N. Then N lines follow, each gives the hobby list of a person in the format:
Ki: hi[1] hi[2] … hi[Ki] where Ki(>0) is the number of hobbies, and hi[j] is the index of the j-th hobby, which is an integer in [1, 1000].

Output Specification

For each case, print in one line the total number of clusters in the network. Then in the second line, print the numbers of people in the clusters in non-increasing order. The numbers must be separated by exactly one space, and there must be no extra space at the end of the line.

Sample Input

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

Sample Output

3
4 3 1

题意

每个人可能有多个不同的爱好,只要有一项爱好相同则视为属于同一社交圈。计算社交圈个数,以及各社交圈人数,按人数降序排列。

代码

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
vector<int> father,isroot;
bool cmp(int a,int b) {
	return a>b;
}
int findFather(int v) {					//查找根结点
	if(v==father[v])	return v;		//找到根节点
	else {
		int F=findFather(father[v]);	//递归寻找father[v]的根结点F
		father[v]=F;					//将根节点赋给father[v]
		return F;
	}
}
void Union(int a,int b) {				//合并两个集合
	int faA=findFather(a);
	int faB=findFather(b);
	if(faA!=faB)	father[faA]=faB;
}
int main() {
	int n,k,t;
	scanf("%d",&n);
	int hobby[1001]= {0};	//hobby[t]表示喜欢活动t的人的编号
	father.resize(n+1);
	isroot.resize(n+1);
	for(int i=1; i<=n; i++) {
		father[i]=i;
	}
	for(int i=1; i<=n; i++) {
		scanf("%d:",&k);
		for(int j=0; j<k; j++) {
			scanf("%d",&t);
			if(hobby[t]==0)	hobby[t]=i;		//若某活动之前没人喜欢过 ,hobby[t]=i
			Union(i,findFather(hobby[t]));
			//findFather(hobby[t])表示喜欢t活动的人所在社交圈的根结点,合并当前节点与该根结点,使他们处于同一社交圈
		}
	}
	for(int i=1; i<=n; i++) {
		isroot[findFather(i)]++;
	}
	int cnt=0;	//统计社交圈个数
	for(int i=1; i<=n; i++) {
		//isroot[i]=0表示不是根节点
		if(isroot[i]!=0)	cnt++;
	}
	sort(isroot.begin(),isroot.end(),cmp);
	printf("%d\n",cnt);
	for(int i=0; i<cnt; i++) {
		printf("%d",isroot[i]);
		if(i!=cnt-1)	printf(" ");
	}
	return 0;
}

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 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 10 ^4.

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

题意

同一幅图片出现的鸟属于同一棵树。每棵树上有多只鸟,要求计算树的棵数和鸟的总数,并根据输入的鸟的编号,判断它们是不是属于同一棵树。

代码

#include <iostream>
using namespace std;
//vector<int> father,isroot;
int father[10001],tree[10001];	//tree[i]用来保存以i为根节点的鸟的个数
bool book[10001];				//表示鸟的id是否存在
int findFather(int x) {
	int a=x;
	while(x!=father[x])	x=father[x];
	while(a!=father[a]) {
		int z=a;
		a=father[a];
		father[z]=x;
	}
	return x;
}
void Union(int a,int b) {
	int faA=findFather(a);
	int faB=findFather(b);
	if(faA!=faB)	father[faA]=faB;
}
int main() {
	int n,k,id,t;
	scanf("%d",&n);
	for(int i=1; i<=10001; i++) {
		father[i]=i;
	}
	for(int i=0; i<n; i++) {
		scanf("%d%d",&k,&id);
		book[id]=true;
		for(int j=1; j<k; j++) {
			scanf("%d",&t);
			book[t]=true;
			Union(id,t);
		}
	}
	for(int i=1; i<=10001; i++) {
		if(book[i]==true) {
			int root=findFather(i);	//找到i号鸟的根结点
			tree[root]++;
		}
	}
	int nbird=0,ntree=0;
	for(int i=1; i<=10001; i++) {
		if(book[i]==true && tree[i]!=0) {
			ntree ++;
			nbird += tree[i];
		}
	}
	printf("%d %d\n",ntree,nbird);
	scanf("%d",&k);
	int a,b;
	for(int i=0; i<k; i++) {
		scanf("%d%d",&a,&b);
		a=findFather(a);
		b=findFather(b);
		if(a==b)	printf("Yes\n");
		else	printf("No\n");
	}
	return 0;
}

比较

不仔细看会觉得两题差不多:
1107:计算社交圈个数以及每个社交圈中的人数,根据每个人喜欢的爱好,若有共同爱好则属于同一个社交圈。
1118:同一张图里出现的鸟属于同一棵树。要求计算每个树上的鸟数,以得到鸟的总数。

两题背景的对应关系:
1107	——	1118
人		——	图片
爱好	——	鸟
社交圈	——	树

所以1107与1118题不同。1107是计算每个社交圈的人数,并非计算每个社交圈中的爱好数,而1118题是计算每棵树的鸟数,相当于计算每个社交圈中的爱好数,与图片数无关
故两题解题思路不同。

惭愧,两题解题思路都参考了柳神:11071118

上一篇:Generate Parentheses


下一篇:acwing 1118分成互质数(DFS搜索顺序)