Input
7 5
3 2 5 4
0
2 1 2
1 1
2 6 7
Output
4 4 1 4 4 2 2
题意:n(人数),m(组数),m行,先输入k,表示这组有k个人,下面是k个人的编号,同组可以传递信息,问当第i个人是信息源时,有几个人知道信息。
思路:并查集,最好用递归的findd函数,先求出F数组(祖先的编号),然后看第i有几个编号相同的。
AC代码:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <sstream>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <map>
#include <set>
#define MAX 0x3f3f3f3f
#define fori(a,b) for(int i=a;i<=b;i++)
#define forj(a,b) for(int j=a;j<=b;j++)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const double PI = acos(-1);
const int M=5e5+10;
#define inf 0x3f3f3f
int rankk[M];
int F[M];
int ans[M];/*
int findd(int n)//找根
{
int root=n;
while(root!=F[root])
root=F[root];
return root;
}*/
int findd(int x)
{
if(x!=F[x])
F[x]=findd(F[x]);
return F[x];
}
void unionn(int x,int y)
{
int root1,root2;
root1=findd(x);
root2=findd(y);
if(root1!=root2)
F[root1]=root2;
}
int main()
{
int m,n,i,j,x,y,k,a,b;
memset(ans,0,sizeof(ans));
cin>>n>>m;
for(i=0;i<=n;i++)
F[i]=i;
while(m--)
{
cin>>k;
if(k!=0)//不要忘记加
cin>>a;
for(i=1;i<k;i++)
{
cin>>b;
unionn(a,b);
}
}
// for(i=1;i<=n;i++)
// cout<<F[i]<<" ";
// cout<<endl;
for(i=1;i<=n;i++)
{
ans[findd(i)]++;
}
cout<<ans[findd(1)];
for(i=2;i<=n;i++)
cout<<" "<<ans[findd(i)];
cout<<endl;
return 0;
}