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
题意:输入n个人,再输入这n个人喜欢的活动编号,如果两个人中任意两个人的活动相同,就认为他们都处于一个社交圈,输出有多少个社交圈,并且按照社交圈的人数从大到小输出社交圈的人数
思路:先写出并查集模板,findfather函数,union函数,和在主函数里面写初始化函数。
结合柳神的博客进行解释:
0. 每个社交圈的结点号是⼈的编号,⽽不是课程。课程是⽤来判断是否处在⼀个社交圈的。
- course[t] 表示任意⼀个喜欢t活动的⼈的编号。如果当前的课程t,之前并没有⼈喜欢过,那么就
course[t] = i ,i为它⾃⼰的编号,表示i为喜欢course[t] 的⼀个⼈的编号 - course[t] 是喜欢t活动的⼈的编号,那么findFather(course[t]) 就是喜欢这个活动的⼈所处的社交圈
⼦的根结点,合并根结点和当前⼈的编号的结点i。即Union(i, findFather(course[t])),把它们处在
同⼀个社交圈⼦⾥⾯ - isRoot[i] 表示编号i的⼈是不是它⾃⼰社交圈⼦的根结点,如果等于0表示不是根结点,如果不等
于0,每次标记isRoot[findFather(i)]++ ,那么isRoot 保存的就是如果当前是根结点,那么这个社交
圈⾥⾯的总⼈数 - isRoot 中不为0的编号的个数cnt就是社交圈圈⼦的个数
- 把isRoot 从⼤到⼩排列,输出前cnt个,就是社交圈⼈数的从⼤到⼩的输出顺序
#include<iostream>
#include<cstdio>
#include<stack>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<map>
#include<cctype>
#include<cstdlib>
#include<ctime>
#include<unordered_map>
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;
}