L2-007 家庭房产 (25分)

这里写自定义目录标题

题目详情

给定每个人的家庭成员和其自己名下的房产,请你统计出每个家庭的人口数、人均房产面积及房产套数。
输入格式:

输入第一行给出一个正整数N(≤1000),随后N行,每行按下列格式给出一个人的房产:

编号 父 母 k 孩子1 … 孩子k 房产套数 总面积
其中编号是每个人独有的一个4位数的编号;父和母分别是该编号对应的这个人的父母的编号(如果已经过世,则显示-1);k(0≤k≤5)是该人的子女的个数;孩子i是其子女的编号。

输出格式:

首先在第一行输出家庭个数(所有有亲属关系的人都属于同一个家庭)。随后按下列格式输出每个家庭的信息:

家庭成员的最小编号 家庭人口数 人均房产套数 人均房产面积
其中人均值要求保留小数点后3位。家庭信息首先按人均面积降序输出,若有并列,则按成员编号的升序输出。

代码实现

#include<iostream>
#include<algorithm>
using namespace std;
int mark[10003]={0},visit[10003]={0};
int find(int x){
    if(mark[x]==x)return x;
    else return find(mark[x]);
}
struct P{
    int mianji,count,sum;//怎么把这些人归到一个家庭里?并查集???
    int fa,ma;
    //vector<int> son;
    P(){
        fa=-1;ma=-1;count=0;mianji=0;sum=0;
    }
}people[10003];
struct A{
	int id;
    float count,mianji,renshu;//房子数量
    A(){
        id=-1;
        count=0;
        mianji=0;
        renshu=0;
    }
}ans[10003];
int markans[10003]={0};
int cmp1(A a, A b) {//对答案进行排序
	if(a.renshu!=0&&b.renshu!=0)
    if(a.mianji/a.renshu != b.mianji/b.renshu)
        return a.mianji/a.renshu > b.mianji/b.renshu;
    else
        return a.id < b.id;
    else if(a.renshu!=0)return 1;
    return 0;
}
int main(){
	for(int i=1;i<=10002;i++)mark[i]=i,ans[i].id=i;
	int cnt=0;
    int n;
    cin>>n;int num[n]={0};
    for(int i=0;i<n;i++){
        cin>>num[i];
        visit[num[i]]=1;
        cin>>people[num[i]].fa>>people[num[i]].ma;
        if(people[num[i]].fa!=-1){
        	visit[people[num[i]].fa]=1;
            find(mark[people[num[i]].fa])<find(mark[num[i]])?(mark[find(mark[num[i]])]=find(mark[people[num[i]].fa])):(mark[find(people[num[i]].fa)]=find(mark[num[i]]));
            //寻找序号最小的那个人
        }if(people[num[i]].ma!=-1){
        	visit[people[num[i]].ma]=1;
            find(mark[people[num[i]].ma])<find(mark[num[i]])?(mark[find(mark[num[i]])]=find(mark[people[num[i]].ma])):(mark[find(people[num[i]].ma)]=find(mark[num[i]]));
        }
        int kid;
        cin>>kid;
        for(int j=0;j<kid;j++){
            int tmp;
            cin>>tmp;
            visit[tmp]=1;//方便统计人数
            find(mark[tmp])<find(mark[num[i]])?(mark[num[i]]=find(mark[tmp])):(mark[tmp]=find(mark[num[i]]));
            //people[num].son.push(tmp);
        }
        cin>>people[num[i]].count>>people[num[i]].mianji;
    }
    for(int i=0;i<10000;i++){ 
		
    	if(visit[i]){
    		if(ans[find(i)].renshu==0)cnt++;ans[find(i)].renshu++;
		}
	}
    for(int i=0;i<n;i++){
        int id=find(num[i]);
        ans[id].id=id;
        ans[id].mianji+=people[num[i]].mianji;
        ans[id].count+=people[num[i]].count;
        //ans[id].renshu++;
        markans[id]=1;
       
    }
    sort(ans,ans+10000,cmp1);
    cout<<cnt<<endl;
    for(int i=0;i<10000;i++){
        if(markans[ans[i].id])printf("%04d %d %.3f %.3f\n",ans[i].id,(int)ans[i].renshu,ans[i].count/ans[i].renshu,ans[i].mianji/ans[i].renshu);
    }
}

算法思路

通过并查集找到一个家庭中最小的那个人,最后再以这个人为根,对所有人的房产,人数,面积进行统计。重点是并查集的使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值