PAT A1107 Social Clusters 题解及注意事项
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 (≤), 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 (>) is the number of hobbies, and [ 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
思路:
关于并查集:并查集-https://www.cnblogs.com/tao10203/p/13855118.html
和"好朋友"问题类似,如果A和B是好朋友,B和C是好朋友,那么A和C就是好朋友,即如果A选了1,2课,B选了1课,C选了2课,那么A,B,C就是同一个cluster中的人,本题中判断两个人是好朋友的条件是他们有公共喜欢的课程,因此不妨开一个数组course,其中course[t]记录任意一个喜欢课程t的人,这样findFather(course[t])就是喜欢这个课的人应该所在的集合的根节点。于是,对当前读入的人的编号I和他喜欢的每个活动t,进行Union(i,course[t])即可。
Solution(C/C++):
#include <bits/stdc++.h> using namespace std; const int maxn = 10010; int father[maxn], course[maxn] = { 0}; // chourse[i] 存任意一个喜欢课程i的人,反正一合并都在一个集合里 void init(int n) { for (int i = 0; i <= n; ++i) { father[i] = i; } } int findFather(int x) { if (x == father[x]) return x; // x就是根节点 else { int F = findFather(father[x]); //查找他的父亲 father[x] = F; return F; } } void Union(int a, int b) { int Fa = findFather(a); int Fb = findFather(b); if (Fa != Fb) father[Fb] = Fa; } bool cmp(int a, int b) { return a > b; } int main() { int n, k, t; cin >> n; init(n); for (int i = 1; i <= n; ++i) { scanf("%d: ", &k); //吸收‘:’符号 for (int j = 0; j < k; ++j) { cin >> t; if (course[t] == 0) { course[t] = i; //如果还没人喜欢课程t,就指定他是喜欢t的人之一 } Union(i, course[t]); // 让i和喜欢course[t]合并到同一个集合 } } int cnt = 0; int cluster[maxn] = {0}; bool isroot[maxn] = {false}; fill(isroot, isroot + maxn, false); for (int i = 1; i <= n; ++i) { int F = findFather(i); if (isroot[F] == false) { isroot[F] = true; cnt++; } cluster[F]++; } cout << cnt << endl; sort(cluster + 1, cluster + n + 1, cmp); for (int i = 1; i <= cnt; ++i) { cout << cluster[i]; if (i < cnt) cout << " "; } return 0; }