题目地址:https://pintia.cn/problem-sets/994805342720868352/problems/994805361586847744
大概意思是具有相同兴趣的人聚成一类。
#include <iostream>
#include <string>
#include <set>
#include <map>
#include<queue>
#include<stack>
#include<algorithm>
//new and delete
//A1107 Social Clusters
using namespace std;
const int MaxN = 1010;
int hob[MaxN]; //每个兴趣被哪个人第一个喜欢
int pe[MaxN]; //人的并查集
int isRoot[MaxN]; //-1代表不是根结点,数字代表集合元素数
//Find the root of the set including x
int FindFather(int x){
int a = x;
while (pe[x] != -1) {
x = pe[x];
}
//optional compression of path
while (pe[a] != -1) {
int z = pe[a];
pe[a] = x;
a = z;
}
return x;
}
//合并a,b所在集合
void Union(int a, int b) {
int root_a = FindFather(a);
int root_b = FindFather(b);
if (root_a != root_b) {
pe[root_b] = root_a; //将b合并到a
isRoot[root_a] = abs(isRoot[root_a])+ abs(isRoot[root_b]);
isRoot[root_b] = -1;
}
}
bool cmp(int a, int b) {
return a > b;
}
void PrintN(int a[], int N) {
for (int i = 0; i < N; i++)
printf("%d ", a[i]);
printf("\n");
}
int main() {
fill(hob, hob + MaxN, -1);
fill(pe, pe + MaxN, -1);
fill(isRoot, isRoot+MaxN, -1);
int N; //the number of people
scanf("%d\n", &N);
for (int i = 0; i < N; i++) { //从第0人到第N-1人
//这里注意,每个人如果不在集合,最开始要自成一类
if (FindFather(i)==i)
isRoot[i] = 1;
/*PrintN(hob, N+5);
PrintN(pe, N);
PrintN(isRoot, N);
printf("\n");*/
int M;
scanf("%d:", &M);
for (int j = 0; j < M; j++) {
int hobby;
scanf("%d", &hobby);
if (hob[hobby] == -1) { //该兴趣没人喜欢
hob[hobby] = i;
}
else { //合并这个人和喜欢该hobby的人
Union(i, hob[hobby]);
}
}
}
vector<int > ans;
for (int i = 0; i < MaxN; i++) {
if (isRoot[i] != -1) {
ans.push_back(isRoot[i]);
}
}
sort(ans.begin(), ans.end(), cmp);
printf("%d\n", ans.size());
for (int i = 0; i < ans.size(); i++) {
printf("%d", ans[i]);
if (i < ans.size() - 1) {
printf(" ");
}
else {
printf("\n");
}
}
}