题目链接
丝路(并查集)
①分类题,一定要明白对谁分类,是对人,而不是对爱好,这决定了father数组的存法
②算法参考自《算法笔记》329页和柳婼,对她的算法进行了一点修改,就是算每个类别的人可以在union的同时顺便求出而不用单独另求
代码
using namespace std;
#include<bits/stdc++.h>
int father[1010],hobby[1010],num[1010],like,n,k,cnt;
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 fa = findfather(a);
int fb = findfather(b);
if (fa != fb) {
father[fb] = fa;
num[fa] += num[fb];
num[fb] = 0;
}
}
int main() {
cin >> n;
for (int a = 1; a <= n; a++)father[a] = a, num[a] = 1;
for (int i = 1; i <= n; i++) {
scanf("%d: ", &k);
for (int j = 0; j < k; j++) {
cin >> like;
hobby[like] = hobby[like] == 0 ? i : hobby[like];
Union(hobby[like], i);
}
}
sort(num + 1, num + n + 1,greater<int>());
for (int i = 1; i <= n; i++) {
if (num[i] != 0)cnt++;
}
cout << cnt << endl;
for (int i = 1; i <= cnt; i++) {
if (i != 1)cout << " ";
cout << num[i];
}
return 0;
}