传送门:点击打开链接
思路:一是并查集,对人的兴趣块祖先计数;二是直接暴力搜索,一个个比较并标记。
代码:
///并查集
#include<bits/stdc++.h>
using namespace std;
int n,p[1005],c[1005],cnt[1005];
int s[1005];
bool cmp(int a,int b){ return a>b;}
int f(int x){
while(x!=p[x]) x=p[x];
return x;
}
int main(){
while(cin>>n){
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=1000;i++) p[i]=i;
for(int i=1;i<=n;i++){
int t,tp,v;
scanf("%d: %d",&t,&c[i]);
for(int j=1;j<t;j++) {
scanf("%d",&v);
int x=f(c[i]),y=f(v);
if(x!=y) p[x]=y;
}
}
for(int i=1;i<=1005;i++)
cnt[f(c[i])]++;
int ct=0;
for(int i=1;i<=1005;i++)
if(cnt[i]) s[ct++]=cnt[i];
sort(s,s+ct);
cout<<ct<<endl;
for(int i=ct-1;i>=0;i--)
cout<<s[i],i==0 ? :cout<<" ";
cout<<endl;
}
}
///暴力搜索
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3+5;
int n,mp[N][N],vis[N];
vector<int> v;
void dfs(int x){
for(int i=1;i<=mp[x][0];i++){
for(int j=1;j<=n;j++){
if(vis[j]) continue;
for(int k=1;k<=mp[j][0];k++){
if(mp[x][i]==mp[j][k]){
vis[j]=1;
v.back()++;
dfs(j);
}
}
}
}
}
int main(){
while(cin>>n){
memset(vis,0,sizeof(vis));
v.clear();
for(int i=1;i<=n;i++){
char c;
cin>>mp[i][0]>>c;
for(int j=1;j<=mp[i][0];j++) cin>>mp[i][j];
}
for(int i=1;i<=n;i++)
if(!vis[i]) vis[i]=1,v.push_back(1),dfs(i);
sort(v.begin(),v.end());
cout<<v.size()<<endl;
for(int i=v.size()-1;i>=0;i--)
cout<<v[i],i==0? :cout<<" ";
cout<<endl;
}
}