题目:
思路分析:
求一个家庭相当于求一个连通块 那么直接并查集的思想就行
不过这里我们合并时候把数字最小的当老祖宗 方便
第一次遍历是求房产数 和 面积的和
第二次遍历是求家族的人数
第三次遍历是计算平均值!
代码实现:
const int MAX=1000010;
struct node{
int id,people;
double sum1,sum2;
};
node q1[MAX],q2[MAX];
node ans[MAX];
int Ra[MAX];
int fa[MAX];
int vis[MAX];
int vis1[MAX];
bool cmp(node a,node b){
if(a.sum2==b.sum2){
return a.id<b.id;
}
return a.sum2>b.sum2;
}
int Find(int x)
{
int temp = x ;
while(fa[temp]!=temp)
temp = fa[temp] ;
return temp;
}
void add(int x , int y)
{
int t1 , t2 ;
t1 = Find(x) ;
t2 = Find(y) ;
if(t1 != t2)
{
if(t1 > t2)
{
fa[t1] = t2 ;
}
else fa[t2] = t1 ;
}
}
//int Find(int x){
// if(x==fa[x]) return x;
// return fa[x]==Find(fa[x]);
//}
//void add(int x,int y){
// int xx=Find(x);
// int yy=Find(y);
// if(xx==yy) return;
// if(xx>yy){
// fa[xx]=yy;
// }
// else {
// fa[yy]=xx;
// }
//}
int main(){
int n,id,f,m,k,son;
cin>>n;
for(int i=0;i<MAX;i++)
fa[i]=i;
for(int i=0;i<n;i++){
cin>>id;
cin>>f>>m;
vis[id]=1;
if(f!=-1){
vis[f]=1;
add(id,f);
}
if(m!=-1){
vis[m]=1;
add(id,m);
}
cin>>k;
for(int i=0;i<k;i++){
cin>>son;
if(son!=-1){
vis[son]=1;
add(id,son);
}
}
cin>>q1[i].sum1;
cin>>q1[i].sum2;
q1[i].id=id;
}
for(int i=0;i<n;i++){
int t=Find(q1[i].id);
q2[t].id=t;
q2[t].sum1+=q1[i].sum1;
q2[t].sum2+=q1[i].sum2;
}
for(int i=0;i<MAX;i++){
if(vis[i]){
int t=Find(i);
q2[t].people++;
}
}
int num=0;
for(int i=0;i<MAX;i++){
if(vis[i]){
int t=Find(i);
if(!vis1[t]){
vis1[t]=1;
double xx=q2[t].people;
ans[num].id=t;
ans[num].people=int(xx);
ans[num].sum1=q2[t].sum1*1.0/xx;
ans[num++].sum2=q2[t].sum2*1.0/xx;
}
}
}
sort(ans,ans+num,cmp);
cout<<num<<endl;
for(int i=0;i<num;i++){
printf("%04d %d %.3f %.3f\n" , ans[i].id,ans[i].people,ans[i].sum1,ans[i].sum2);
}
}