明显是并查集的问题,但是一开始不知道怎么合并,参考的《算法笔记》的答案,每次碰到一个爱好,就给这个爱好设置为有这个爱好的人,这样就有了合并对象:人和有这个爱好的人
剩下的就是模板了,初始化,查找根节点,合并
#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;
const int maxn = 1e3 + 10;
int father[maxn], course[maxn], cnt[maxn];
int n;
void init()
{
for (int i = 1; i <= n; i++)father[i] = i;
}
int findfather(int x)
{
while (x != father[x])x = father[x];
return x;
}
void Union(int a, int b)
{
int fa = findfather(a);
int fb = findfather(b);
father[fa] = fb;
}
int main()
{
scanf("%d", &n);
init();
for (int i = 1; i <= n; i++)
{
int k;
scanf("%d:", &k);
while (k--)
{
int x;
scanf("%d", &x);
if (course[x] == 0)course[x] = i;
Union(course[x], i);
}
}
for (int i = 1; i <= n; i++)
cnt[findfather(father[i])]++;
vector<int>a;
for (int i = 1; i <= n; i++)
{
if (cnt[i] != 0)a.push_back(cnt[i]);
}
sort(a.begin(), a.end(), greater<int>());
printf("%d\n", a.size());
for (int i = 0; i < a.size(); i++)
{
printf("%d", a[i]);
if (i != a.size() - 1)printf(" ");
}
return 0;
}