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;
}


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