题目本身不难,但是由于对并查集的路径压缩理解有误,导致改了很长时间
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 1100;
int father[maxn], hobby[maxn] = { 0 };
bool cmp(int a, int b) { return a > b; }
void init() { for (int i = 0; i < maxn; i++) { father[i] = i; } }
int Findfather(int x) {
if (father[x] == x) { return x; }
else {
int F = Findfather(father[x]);
father[x] = F;
return F;
}
}
void Union(int a, int b) {
int Fa = Findfather(a), Fb = Findfather(b);
if (Fa != Fb) { father[Fa] = Fb; }
}
int main() {
init();
int n;
cin >> n;
for (int i = 1; i <= n; i++) {//i is the people's id
int k, t;
scanf("%d: ", &k);//cin >> k;
for (int j = 0; j < k; j++) {
cin >> t;//t is hobby id
if (hobby[t] == 0) { hobby[t] = i; }
else { Union(i, hobby[t]); }
}
}
int cnt = 0, Root[maxn] = { 0 };
for (int i = 1; i <= n; i++) {
if (father[i] == i) { cnt++; }
Root[Findfather(i)]++;//路径已经完全压缩了,但是为什么用root[father[i]]就不对呢?
}//因为路径压缩后的结果不总是个菊花图(即一个根节点其余全是叶节点),因为每次压缩只影响该节点之上的节点。
sort(Root, Root + n + 1, cmp);//注意最大为n+1个值
cout << cnt << endl << Root[0];
for (int i = 1; i < n; i++) {
if (Root[i] == 0) { break; }
cout << ' ' << Root[i];
}
return 0;
}