https://pintia.cn/problem-sets/994805342720868352/problems/994805356599820288
挺好的一个并查集,先读入然后再处理。注意:在并查集合并的时候选编号小的作为根。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int p[N],people[N],home_cnt[N],st[N],n;
double area[N];
struct node{
int a,b;}temp;
struct family
{
int id,cnt;
double avg,area;
};
vector<node>ve;
vector<family>ans;
bool cmp(family a,family b)
{
if(a.area==b.area)
return a.id<b.id;
return a.area>b.area;
}
int find(int x)
{
if(x!=p[x]) p[x]=find(p[x]);
return p[x];
}
int main(void)
{
cin>>n;
for(int i=0;i<N;i++) p[i]=i,people[i]=1;
for(int i=0;i<n;i++)
{
int id,month,father,k; cin>>id>>month>>father>>k;
st[id]=1;
if(month!=-1) ve.push_back({
id,month}),st[month]=1;
if(father!=-1) ve.push_back({
id,father}),st[father]=1;
for(int j=0;j<k;j++)
{
int x; cin>>x; st[x]=1;
ve.push_back({
id,x});
}
cin>>home_cnt[id]>>area[id];
}
for(int i=0;i<ve.size();i++)
{
int a=ve[i].a,b=ve[i].b;
int fa=find(a),fb=find(b);
if(fa!=fb)
{
if(fa>fb) swap(fa,fb);//选小结点作为根
people[fa]+=people[fb];
home_cnt[fa]+=home_cnt[fb];
area[fa]+=area[fb];
p[fb]=fa;
}
}
for(int i=0;i<N;i++)
if(st[i]&&p[i]==i)//如果该点存在,且是该集合的根
{
ans.push_back({
i,people[i],home_cnt[i]*1.0/people[i],area[i]/people[i]});
}
sort(ans.begin(),ans.end(),cmp);
cout<<ans.size()<<endl;
for(int i=0;i<ans.size();i++)
printf("%04d %d %.3lf %.3lf\n",ans[i].id,ans[i].cnt,ans[i].avg,ans[i].area);
return 0;
}