GPLT L2-007. 家庭房产【并查集】

题目:家庭房产

思路:利用并查集分类家族即可。

开始存储每个人的房数和面积时我用了一个结构体,然后下标为当前人的编号,最后用findd函数寻找到各自的家族的根后加入家族的存储对应值即可。

还有是用一个标记数组将预先输入的编号标记,这样在查找家族数时就可以排除那些压根没有的值了!

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 10000;
int n,f[maxn+5];
struct family{
    int houses,area;
}val[maxn];
struct whl{
    int id,persons;
    double hs,aas;
}ans[maxn];
int visit[maxn+5];
bool cmp(whl x,whl y){//排序
    if(x.aas == y.aas) return x.id < y.id;
    return x.aas > y.aas;
}
void init(){//初始化
    for(int i=0;i<=maxn;i++) f[i] = i;
    memset(visit,0,sizeof(visit));
    memset(val,0,sizeof(val));
}
int findd(int v){//寻找根节点
    if(v != f[v]) f[v] = findd(f[v]);
    return f[v];
}
void mergee(int u,int v){//合并
    int fu = findd(u),fv = findd(v);
    if(fu != fv) f[fv] = fu;
}
int main()
{
    int id[1005],far,mou,k,child;
    while(~scanf("%d",&n)){
        init();//初始化
        for(int i=0;i<n;i++){
            scanf("%d%d%d%d",&id[i],&far,&mou,&k);
            visit[id[i]] = 1;//标记出现的编号
            if(far != -1) {mergee(id[i],far);visit[far] = 1;}//家族合并
            if(mou != -1) {mergee(id[i],mou);visit[mou] = 1;}//家族合并
            for(int j=0;j<k;j++){
                scanf("%d",&child);
                visit[child] = 1;//标记出现编号
                mergee(id[i],child);//家族合并
            }
            scanf("%d%d",&val[id[i]].houses,&val[id[i]].area);//将每组的房数和面积存入对应本组的第一个人的编号
        }
        int cnt = 0;
        for(int i=0;i<=maxn;i++)//扫一遍编号,将没有改变的值存入,即根节点
                if(visit[i] && f[i] == i) ans[cnt++].id = i;
        //开始进行家族的人数,房数,面积的计算
        for(int i=0;i<cnt;i++){
            int record = 999999,num = 0;
            for(int j=0;j<=maxn;j++)
                if(visit[j] && findd(j) == ans[i].id){//将于先前的根节点比较,当查找的编号的父节点于当前的父节点相等即为同一家族
                    num++;//累计家族人数
                    ans[i].hs += val[j].houses;//累计房数
                    ans[i].aas += val[j].area;//累计面积
                    record = min(record,j);//记录家族中最小编号
                }
            ans[i].id = record;//更新家族最小编号
            ans[i].aas /= (double)num;//计算平均面积
            ans[i].hs /= (double)num;//计算平均房数
            ans[i].persons = num;//保存人数
        }
        sort(ans,ans+cnt,cmp);//按要求排序
        printf("%d\n",cnt);
        for(int i=0;i<cnt;i++) printf("%04d %d %.3lf %.3lf\n",ans[i].id,ans[i].persons,ans[i].hs,ans[i].aas);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章