L3-003 社交集群 (30 分)
题目
思路
开始想复杂了,以为用并查集可能做不了,后来发现其实就是并查集。至于部分爱好相同如何连接,我采用的方法是输入一个爱好之后去判断这个爱好的表当前是否为空,不为空就和表里的第一个人相连,并且无论是否是空的都放入表中。最后取出每个人的祖先放入set同时统计人数即可。
代码
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f3f3f
#define pb push_back
using namespace std;
typedef pair<int, int> P;
const int N = 1e4 + 10;
const int M = 1e2 + 10;
typedef long long ll;
int par[N];
int rnk[N];
void init(int n)
{
for(int i = 0; i <= n; i++)
{
par[i] = i;
}
}
int find(int x)
{
if(x == par[x])
return x;
return x = find(par[x]);
}
void unite(int x, int y)
{
x = find(x);
y = find(y);
if(x == y)
return ;
if(rnk[x] > rnk[y])
{
par[y] = x;
}
else
{
par[x] = y;
if(rnk[x] == rnk[y])
rnk[y]++;
}
}
vector<int> h[N];
vector<int> p[N];
set<int> st;
int num[N];
priority_queue<int> que;
int main()
{
int n;
scanf("%d", &n);
init(1000);
for(int i = 1; i <= n; i++)
{
int k;
scanf("%d: ", &k);
for(int j = 0, x; j < k; j++)
{
cin >> x;
if(p[x].size())
{
unite(p[x][0], i);
}
p[x].pb(i);
}
}
for(int i = 1; i <= n; i++)
{
st.insert(find(i));
num[find(i)]++;
}
cout << st.size() << endl;
bool flag = 0;
for(auto i : st)
{
que.push(num[i]);
}
while(!que.empty())
{
cout << que.top();
que.pop();
if(que.size())
cout << ' ';
}
return 0;
}