一开始并查集的union函数写错,导致测试点1,4,5过不了。
union函数必要从两个顶级根节点去赋值,这样才会使得两个分支连通起来。
附本人AC代码:
#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
int father[1010], hobby[1010];
int N;
map<int, int>Ma;
void init() {
for (int i = 1; i <= N; i++)father[i] = i;
}
int findfather(int x) {
int t = x;
while (father[x] != x) {
x = father[x];
}
while (father[t] != x) {
int m = father[t];
father[t] = x;
t = m;
}
return x;
}
void uni(int x, int y) {
int fx = findfather(x);
int fy = findfather(y);
if (fx != fy) {
if (fy>fx)father[fx] = fy;
else father[fy] = fx;
}
}
int main() {
int num, val;
scanf("%d", &N);
init();
fill(hobby, hobby + 1010, -1);
for (int i = 0; i < N; i++) {
scanf("%d:", &num);
for (int j = 0; j < num; j++) {
scanf("%d", &val);
if (hobby[val] == -1)hobby[val] = i + 1;
else {
uni(i + 1, hobby[val]);
}
}
}
for (int i = 1; i <= N; i++) {
Ma[findfather(i)]++;
}
vector<int>ans;
for (auto it = Ma.begin(); it != Ma.end(); it++) {
ans.push_back(it->second);
}
sort(ans.begin(), ans.end());
printf("%d\n", ans.size());
for (int i = ans.size() - 1; i >= 0; i--) {
if (i == ans.size() - 1)printf("%d", ans[i]);
else printf(" %d", ans[i]);
}
printf("\n");
return 0;
}