L2-007. 家庭房产

 

使用并查集

参考:http://blog.csdn.net/sinat_30126425/article/details/51901934

 

 

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define max 10010;
int visit[10001], symbol[10001];
int unionStorage[10001];
struct housing
{
double housingUnit;
double housingArea;
int id;
int num;
housing()
{
id = -1;
}
};

void initializer()
{
for(int i=0; i<10001; i++)
unionStorage[i] = i;
}

int findRoot(int id)
{
if(id!=unionStorage[id])
return findRoot(unionStorage[id]);
else
return id;
}

bool compare(housing a, housing b)
{
if(a.housingArea!=b.housingArea)
return a.housingArea > b.housingArea;
else
return a.id < b.id;
}

void unionOperator(int a, int b)
{
int x = findRoot(a);
int y = findRoot(b);
if(x!=y)
{
if(x>y)
unionStorage[x] = y; //the smaller number is father of bigger number
else
unionStorage[y] = x;
}

}
int main()
{
housing first[1001], stastics[10001], second[1001];
initializer();
memset(visit, 0, sizeof(visit));
memset(symbol, 0, sizeof(symbol));
int n, temp1, temp2, k, child; //k is the number of children
cin >> n;
for(int i=0; i<n; i++)
{
cin >> first[i].id >> temp1 >> temp2;
visit[first[i].id] = 1;
if(temp1!=-1)

{
unionOperator(temp1, first[i].id);
visit[temp1] = 1;
}
if(temp2!=-1)
{
unionOperator(temp2, first[i].id);
visit[temp2] = 1;
}
cin >> k;
for(int j=0; j<k; j++)
{
cin >> child;
if(child!=-1)
{
unionOperator(child, first[i].id);
visit[child] = 1;
}

}
cin >> first[i].housingUnit >> first[i].housingArea;
}
int memory = 0;
for(int i=0; i<n; i++) //统计,一个集合中所有的元素,将房产面积和个数相加
{
int id = findRoot(first[i].id);
if(stastics[id].id != id)
symbol[memory++] = id;
stastics[id].id = id;
stastics[id].housingUnit +=first[i].housingUnit; //前i个节点都是数据
stastics[id].housingArea +=first[i].housingArea; //统计前i个节点

}

for(int i=0; i<10000; i++)
{
if(visit[i])
{
stastics[findRoot(i)].num++; //对于出现过的每一个成员,找到根,为家庭成员的数量加1
}
}
int housingNumber = 0; //家庭个数
for(int i=0; i<memory; i++) //这里和原作者有少许区别,原作者使用symbol数组来标记只有根节点才进行以下运算,这里使用symbol数组记录了所有的根节点,直接进行运算,避免了遍历0-10000才能找出所有的根节点
{


double x = (double)stastics[symbol[i]].num;
second[housingNumber].housingUnit = stastics[symbol[i]].housingUnit / x;
second[housingNumber].housingArea = stastics[symbol[i]].housingArea / x;
second[housingNumber].id = symbol[i];
second[housingNumber++].num = (int)x;

}
sort(second, second+housingNumber, compare);
cout << housingNumber << endl;
for(int i=0; i<housingNumber; i++)
{
printf("%04d %d %0.3lf %0.3lf\n", second[i].id, second[i].num, second[i].housingUnit, second[i].housingArea);
}
return 0;
}

 

 

代码2:参考自上边提供的链接,完全抄过来的,有注释

/* ***********************************************
Author        :yzkAccepted
Created Time  :2016/7/13 20:28:02
TASK          :ggfly.cpp
LANG          :C++
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <stack>
using namespace std;
const int maxn=11000;
int vis[maxn],m[maxn];
int p[10010];  //the union is represent by array,four didit number so the capacity of array i
struct node{
    double ans1,ans2;
    int id,num;
};

bool cmp(node a,node b){
    if(a.ans2!=b.ans2)
        return a.ans2>b.ans2;   //per capita real estate area from biggest to small
    return a.id<b.id;  //成员编号由小到大
}

void init(){

    for(int i=0;i<=10000;i++)  //初始化p[i];
        p[i]=i;
}

int find(int x)  //find operator
{
    if(x==p[x])
        return x;
    else
        return p[x]=find(p[x]);  //recursive
}

void un(int a,int b){
    int x=find(a);
    int y=find(b);
    if(x!=y){  //if x = y,this is root node
        if(x>y)
            p[x]=y;  //y become the father of x
        else
            p[y]=x;  //x become the father of y
    }
}


int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int i,j,n;
    node a[10005];
    node b[10005];
    node mul[10005];
    cin>>n;
    init();  //数组初始化p[i]==i
    memset(vis,0,sizeof(vis));
    memset(m,0,sizeof(m));
    for(i=0;i<n;i++)
    {
        int p1,p2,d,k;
        cin>>a[i].id>>p1>>p2;
        vis[a[i].id]=1;  //表示这个人员已经访问过
        if(p1!=-1){ // parent is still alive
            un(p1,a[i].id);  //union  p1 and a[i].id
            vis[p1]=1;  //p1 is already visited
        }
        if(p2!=-1){
            un(p2,a[i].id);
            vis[p2]=1;
        }
        cin>>k;
        while(k--){
            cin>>d;
            if(d!=-1){
                un(a[i].id,d);
                vis[d]=1;
            }
        }
        cin>>a[i].ans1>>a[i].ans2;
    }
    for(i=0;i<n;i++){
        int id=find(a[i].id);
        mul[id].id=id;  //get a[i] root
        mul[id].ans1+=a[i].ans1;  //summation of housing units
        mul[id].ans2+=a[i].ans2;    //summation of housing area
    }
     for(i=0; i<10000; i++)
            if(vis[i])   //i node is visited,
            {   mul[find(i)].num++;  //the root node of i number's num +1
            }
    int cnt=0;
    for(i=0;i<10000;i++){
        if(vis[i]){
            int id=find(i);
            if(!m[id]){
                m[id]=1;
                double x=double(mul[id].num);  //convert the person number of house from int to double
                b[cnt].ans1=mul[id].ans1*1.0/x;
                b[cnt].ans2=mul[id].ans2*1.0/x;
                b[cnt].id=id;
                b[cnt++].num=int(x);
            }
        }
    }
    cout<<cnt<<endl;
    sort(b,b+cnt,cmp);
    for(i=0;i<cnt;i++)
        printf("%04d %d %.3lf %.3lf\n",b[i].id,b[i].num,b[i].ans1,b[i].ans2);
    return 0;
}

 

posted @ 2017-08-17 18:05  diamondDemand  阅读(186)  评论(0)    收藏  举报