L2-007 家庭房产 题解

L2-007 家庭房产:

思路:

1.因为要根据题给的隐藏关系划分家庭,所以并查集

2.合并操作的UNION函数做一些小小的变化,保证根结点是集合中数值最小的

3.记录每个人的房产数,房产总面积,并在最后加到大家庭(集合)的数据中

#include<cstdio>
#include<map>//使用到pair
#include<algorithm>//sort
using namespace std;
typedef pair<float,float> geren;//定义一个名为geren的floa对floa的数据类型
const int N=10010;//编号是四位数
//用于记录划家庭(集合)后每个家庭的情况
struct jiaxinxi{
    int hao;
    int ren=0;//后面记录大家庭人数时包括了根结点自己,所以此处为0
    float junnum=0;
    float juns=0;
}xinxi[N];
int n;
int father[N];
//本题中由题目给出出现的编号,并不是从1~n所有的数都出现,所以使用一个bool的数组记录出现的数字编号
bool isroot[N],chuxian[N]={false};
void init( ){
    for(int i=0;i<N;i++){
        father[i]=i;
        isroot[i]=false;
    }
}
int findfather(int x){
    while(x!=father[x]){
        x=father[x];
    }
    return x;
}
void UNION(int a,int b){
    int fa=findfather(a);
    int fb=findfather(b);
    if(fa!=fb){
        /*由于题目要求输出每个家庭中最小的编号,所以在合并集合时让数值相对小的编
        号作为根结点,这样最后划分完后每个集合的根结点就是该集合中的数值最小的编号*/
        if(fa<fb)
            father[fb]=fa;
        else
            father[fa]=fb;
    }
}
//结构体比较函数
bool cmp(jiaxinxi a,jiaxinxi b){
    if(a.juns!=b.juns) return a.juns>b.juns;//面积先大后小
    else return a.hao<b.hao;//编号先小后大
}
int main(){
    int i,j,numk,numj=0,ji,fu,mu,zi;
    geren zijixinxi[N];//用于记录每个人的房产数,房产总面积
    scanf("%d",&n);
    init();
    for(i=0;i<n;i++){
        //自己,父亲,母亲,儿子数量
        scanf("%d %d %d %d",&ji,&fu,&mu,&numk);
        chuxian[ji]=true;//标记编号出现
        if(fu!=-1){
            UNION(ji,fu);
            chuxian[fu]=true;
        }
        if(mu!=-1){
            UNION(ji,mu);
            chuxian[mu]=true;
        }
        for(j=0;j<numk;j++){
            scanf("%d",&zi);
            UNION(ji,zi);
            chuxian[zi]=true;
        }
        scanf("%f %f",&zijixinxi[ji].first,&zijixinxi[ji].second);
    }
    //对出现的编号,寻找他们的根结点并标记
    for(i=0;i<N;i++){
        if(chuxian[i]){
            isroot[findfather(i)]=true;
        }
    }
    //寻找根结点,记数并记录在大家庭情况的结构体数组中
    for(i=0;i<N;i++){
        if(chuxian[i]){
            if(isroot[i]){
                xinxi[numj++].hao=i;
            }
        }
    }
    for(i=0;i<N;i++){
        if(chuxian[i]){
            for(j=0;j<numj;j++){
                //如果当前编号是这个大家庭中的人
                if(findfather(i)==xinxi[j].hao){
                    xinxi[j].ren++;
                    xinxi[j].junnum+=zijixinxi[i].first;
                    xinxi[j].juns+=zijixinxi[i].second;
                    break;//集合间不会有交集,执行完直接跳出
                }
            }
        }
    }
    //计算平均值
    for(i=0;i<numj;i++){
        xinxi[i].junnum=xinxi[i].junnum/xinxi[i].ren;
        xinxi[i].juns=xinxi[i].juns/xinxi[i].ren;
    }
    //按题目要求排序
    sort(xinxi,xinxi+numj,cmp);
    //输出
    printf("%d\n",numj);
    for(i=0;i<numj;i++){
        printf("%04d %d %.3f %.3f\n",xinxi[i].hao,xinxi[i].ren,xinxi[i].junnum,xinxi[i].juns);
    }
}
全部评论

相关推荐

饥饿的长颈鹿就要上岸...:简历五项结构 简历只放五项内容,顺序和格式如下: 一、个人信息 只写名字、电话、邮箱 不写性别、年龄、籍贯、政治面貌、微信等额外信息 二、教育经历 格式:学校名称 | 学历 | 专业 | 就读时间 从左到右排列,一行写完 如果专业和岗位对口,写1-2行主修课程;不对口就不写 学历如果不占优势,可以把教育经历放到简历靠后的位置 三、实习/项目经历 如果没有实习经历,全部写项目经历 每条经历格式:项目名 + 岗位名 + 任职时间段 下面写三到五条工作内容 每条工作内容开头必须用四个字概括,加粗,后面跟一条完整描述 所有描述必须用STAR法则来写(情境-任务-行动-结果) 每一条都要有数据支撑和具体成果 四、个人优势 可以写获得的奖项、证书 如果奖项不够,就写你熟练掌握的技能 每条也要有具体数据或成果支撑,不能空泛堆砌 五、整体要求 一页纸,不要超过一页 个人信息只写名字加电话邮箱 贝贝试一下这个方式写简历,我虽然没收到offer,至少收到了好几轮面试
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务