PAT甲题题解-1114. Family Property (25)-(并查集模板题)

题意:给出每个人的家庭成员信息和自己的房产个数与房产总面积,让你统计出每个家庭的人口数、人均房产个数和人均房产面积。第一行输出家庭个数,随后每行输出家庭成员的最小编号、家庭人口数、人均房产个数、人均房产面积。

并查集,合并的时候编号小的作为父亲节点,最后父亲节点一样的即属于一个家庭,其它都是细节处理没啥好说了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
using namespace std;
/*
并查集
*/
const int maxn=10000+5;
int vis[maxn];
struct UF{
    int father[maxn];
    void init(){
        for(int i=0;i<maxn;i++){
            father[i]=i;
        }
    }
    int find_root(int x){
        if(father[x]!=x){
            father[x]=find_root(father[x]);
        }
        return father[x];
    }
    void Union(int a,int b){
        int fa=find_root(a);
        int fb=find_root(b);
        if(fa!=fb){
            father[max(fa,fb)]=min(fa,fb); //最小编号的作为祖先
        }
    }
}uf;

struct Person{
    int id;
    int dad,mom;
    int k;
    int child[5];
    int m_estate;
    int area;
}person[maxn];

struct Family{
    int minid;  //家庭成员最小编号
    int m=0;  //家庭人口数
    int m_estate=0;  //总房产数目
    int totarea=0;   //总房产面积
    float AVG_sets;  //人均房产个数
    float AVG_area;  //人均房产面积
    bool operator<(const Family tmp)const{
        if(AVG_area==tmp.AVG_area){
            return minid<tmp.minid;
        }
        else{
            return AVG_area>tmp.AVG_area;
        }
    }
}family[maxn];

int main()
{
    int n,id;
    scanf("%d",&n);
    uf.init();
    memset(vis,0,sizeof(vis));
    for(int i=0;i<maxn;i++)
        person[i].id=-1;
    for(int i=0;i<n;i++){
        scanf("%d",&id);
        person[id].id=id;
        scanf("%d %d %d",&person[id].dad,&person[id].mom,&person[id].k);
        vis[person[id].id]=1; //标记出现过的编号
        if(person[id].dad!=-1){
            uf.Union(id,person[id].dad);
            vis[person[id].dad]=1;
        }
        if(person[id].mom!=-1){
            uf.Union(id,person[id].mom);
            vis[person[id].mom]=1;
        }
        for(int j=0;j<person[id].k;j++){
            scanf("%d",&person[id].child[j]);
            uf.Union(id,person[id].child[j]);
            vis[person[id].child[j]]=1;
        }
        scanf("%d %d",&person[id].m_estate,&person[id].area);
    }
    int idArray[maxn];
    int cnt=0;
    for(int i=0;i<maxn;i++){
        if(vis[i]==1){
            idArray[cnt++]=i;  //出现过的编号存起来
        }
    }
    memset(vis,0,sizeof(vis));
    int u,fa;
    for(int i=0;i<cnt;i++){
        u=idArray[i];
        fa=uf.find_root(idArray[i]);
        vis[fa]=1;  //标记父亲节点
        family[fa].minid=fa;
        family[fa].m++;
        if(person[u].id!=-1){
            family[fa].totarea+=person[u].area;
            family[fa].m_estate+=person[u].m_estate;
        }
    }
    int familyNum=0;
    for(int i=0;i<maxn;i++){
        if(vis[i]){
            familyNum++;
            family[i].AVG_sets=family[i].m_estate*1.0f/family[i].m;
            family[i].AVG_area=family[i].totarea*1.0f/family[i].m;
        }
    }
    sort(family,family+maxn);
    printf("%d\n",familyNum);
    for(int i=0;i<familyNum;i++){
        printf("%04d %d %.3f %.3f\n",family[i].minid,family[i].m,family[i].AVG_sets,family[i].AVG_area);
    }
    return 0;
}

时间: 2024-10-12 13:01:45

PAT甲题题解-1114. Family Property (25)-(并查集模板题)的相关文章

1114 Family Property(并查集)

题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805356599820288 题目比较麻烦,因为限时200ms,所以要用散列. 1 #include<iostream> 2 #include<vector> 3 #include<unordered_map> 4 #include<algorithm> 5 using namespace std; 6 7 struct Nod

poj 2524 求连通分量(并查集模板题)

求连通分量 Sample Input 10 91 21 31 41 51 61 71 81 91 1010 42 34 54 85 80 0Sample Output Case 1: 1Case 2: 7 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <cmath> 6 # include

hdu 1213 求连通分量(并查集模板题)

求连通分量 Sample Input2 //T5 3 //n m1 2// u v2 34 5 5 12 5 Sample Output24 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <cmath> 6 # include <queue> 7 # define LL long

hdu 1232 变成生成树至少还要加几条边 (并查集模板题)

求一个图 变成生成树至少还要加几条边(成环的边要删掉,但不用统计) Sample Input4 2 //n m1 3//u v4 33 31 21 32 35 21 23 5999 00 Sample Output102998 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <cmath> 6

How Many Tables——并查集模板题

题目链接 题意: n个人参加晚宴;完全不认识的两个人不能被分配在同一餐桌;认识具有传递性:A认识B B认识C,那么A和C也认识. 题解: 将认识两个人合并到同一集合:最后统计有多少个不同的集合即可; 代码: #include<iostream> #include<stdio.h> #include<math.h> using namespace std; typedef long long ll; const int maxn=5e5+5; int f[maxn]; i

G - Brain Network (easy)(并查集水题)

G - Brain Network (easy) Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u CodeForces 690C1 Description One particularly well-known fact about zombies is that they move and think terribly slowly. While we still don't know

【HDU1232】畅通工程(并查集基础题)

裸敲并查集,很水一次AC 1 #include <iostream> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cstdio> 5 #include <cctype> 6 #include <cmath> 7 #include <algorithm> 8 #include <numeric> 9 #include <string> 1

【HDU1856】More is better(并查集基础题)

裸并查集,但有二坑: 1.需要路径压缩,不写的话会TLE 2.根据题目大意,如果0组男孩合作的话,应该最大的子集元素数目为1.所以res初始化为1即可. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <numeric> 7 #include <

【HDU1325】Is It A Tree?(并查集基础题)

有以下坑点: 1.结束输入不一定-1,题目中的叙述只是说所有权值都为正值. 2.是否构成一棵树不能只判断是否只有一个根节点,没有环路,而且还需要判断每个节点的入度一定是1,不然就不是一棵树. (无环路也可用树的性质:结点数 = 边树 + 1 来取代) 1 #include <iostream> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cctype> 5 #include <cmath&