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:

K​i​​: h​i​​[1] h​i​​[2] ... h​i​​[K​i​​]

where K​i​​ (>0) is the number of hobbies, and h​i​​[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

题意:输入n个人,再输入这n个人喜欢的活动编号,如果两个人中任意两个人的活动相同,就认为他们都处于一个社交圈,输出有多少个社交圈,并且按照社交圈的人数从大到小输出社交圈的人数
思路:先写出并查集模板,findfather函数,union函数,和在主函数里面写初始化函数。
结合柳神的博客进行解释:
0. 每个社交圈的结点号是⼈的编号,⽽不是课程。课程是⽤来判断是否处在⼀个社交圈的。

  1. course[t] 表示任意⼀个喜欢t活动的⼈的编号。如果当前的课程t,之前并没有⼈喜欢过,那么就
    course[t] = i ,i为它⾃⼰的编号,表示i为喜欢course[t] 的⼀个⼈的编号
  2. course[t] 是喜欢t活动的⼈的编号,那么findFather(course[t]) 就是喜欢这个活动的⼈所处的社交圈
    ⼦的根结点,合并根结点和当前⼈的编号的结点i。即Union(i, findFather(course[t])),把它们处在
    同⼀个社交圈⼦⾥⾯
  3. isRoot[i] 表示编号i的⼈是不是它⾃⼰社交圈⼦的根结点,如果等于0表示不是根结点,如果不等
    于0,每次标记isRoot[findFather(i)]++ ,那么isRoot 保存的就是如果当前是根结点,那么这个社交
    圈⾥⾯的总⼈数
  4. isRoot 中不为0的编号的个数cnt就是社交圈圈⼦的个数
  5. 把isRoot 从⼤到⼩排列,输出前cnt个,就是社交圈⼈数的从⼤到⼩的输出顺序
#include
#include
#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;

vector<int> father,isRoot;

int cmp1(int a, int b) {
	return a > b;
}

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,t,cnt = 0;
	int course[1001] = {0};
	scanf("%d",&n);
	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(course[t] == 0) {
				course[t] = i;
			}
			Union(i, findFather(course[t]));
		}
	}
	for(int i = 1; i <= n; i++) {
		isRoot[findFather(i)]++;
	}
	for(int i = 1; i <= n; i++) {
		if(isRoot[i] != 0) cnt++;
	}
	printf("%d\n", cnt);
	sort(isRoot.begin(), isRoot.end(), cmp1);
	for(int i = 0; i < cnt; i++) {
		printf("%d", isRoot[i]);
		if(i != cnt - 1) printf(" ");
	}
	return 0;
}

你可能感兴趣的:(PAT甲级)