浅用一下并查集 也可以用带权并查集
#include<bits/stdc++.h>
using namespace std;
map<int,int>mp;
const int maxn=305;
//bool number[maxn + 5];
int n,m,sum,cnt;
#define PI 3.141592653
typedef long long ll;
//ll dp[100000];
//int v[100000];
int p[100000];
int dp[1007][1007];
int flag=0,ans[1007];
int dis[1007];
int find (int x){
return x==p[x]?x:p[x]=find(p[x]);
}
void join(int x,int y){
x=find(x);
y=find(y);
if(x!=y) p[x]=y;
}
bool cmp(int a,int b){
return ans[a]>ans[b];
}
int main(){
int n;cin>>n;
for(int i=1;i<=n;i++){
p[i]=i;
int t; scanf("%d:",&t);
for(int j=1;j<=t;j++){
int x; cin>>x;
dp[i][x]=1;
}
}
for(int i=1;i<n;i++){
for(int j=i+1;j<=n;j++){
for(int k=1;k<=1000;k++){
if(dp[i][k]&&dp[j][k]){
join(i,j);
break;
}
}
}
}
for(int i=1;i<=n;i++){
int k=find(i);
if(k==i){
dis[++cnt]=k;
}
// cout<<k<<endl;
ans[k]++;
}
sort(dis+1,dis+cnt+1,cmp);
cout<<cnt<<endl;
for(int i=1;i<=cnt;i++){
if(i==1) cout<<ans[dis[i]];
else cout<<" "<<ans[dis[i]];
}
return 0;
}