思路:并查集,最后再统计每个结点的父节点是哪个。
传送门
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int pre[500005];
int sum[500005];
int n, m;
int Find(int root)
{
int son = root;
while(pre[root] != root)
root = pre[root];
while(son != root)//tmp保存前驱结点
{
int tmp = pre[son];
pre[son] = root;
son = tmp;
}
return root;
}
int main()
{
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++)
pre[i] = i;
int cnt = n;
for(int i = 1; i <= m; i++)
{
int u, v;
int t;
scanf("%d", &t);
int root1, root2;
if(t != 0)
{
scanf("%d", &v);
root1 = Find(v);
t--;
}
while(t--)
{
scanf("%d", &u);
root2 = Find(u);
if(root1 != root2)
{
pre[root2] = root1;
cnt--;
}
}
}
for(int i = 1;i <= n;i++)
{
pre[i] = Find(i);
sum[pre[i]]++;
//cout << pre[i] << endl;
}
for(int i = 1;i <= n;i++)
{
if(i == n)
printf("%d",sum[pre[i]]);
else printf("%d ",sum[pre[i]]);
}
return 0;
}