1114. Family Property (25)

时间限制

150 ms

内存限制

65536 kB

代码长度限制

16000 B

判题程序

Standard

作者

CHEN, Yue

This time, you are supposed to help us collect the data for family-owned property. Given each person's family members, and the estate(房产)info under his/her own name, we need to know the size of each family, and the average area and number of sets of their real estate.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (<=1000). Then N lines follow, each gives the infomation of a person who owns estate in the format:

ID Father Mother k Child1 ... Childk M_estate Area

where ID is a unique 4-digit identification number for each person; Father and Mother are the ID's of this person's parents (if a parent has passed away, -1 will be given instead); k (0<=k<=5) is the number of children of this person; Childi's are the ID's of his/her children; M_estate is the total number of sets of the real estate under his/her name; and Area is the total area of his/her estate.

Output Specification:

For each case, first print in a line the number of families (all the people that are related directly or indirectly are considered in the same family). Then output the family info in the format:

ID M AVG_sets AVG_area

where ID is the smallest ID in the family; M is the total number of family members; AVG_sets is the average number of sets of their real estate; and AVG_area is the average area. The average numbers must be accurate up to 3 decimal places. The families must be given in descending order of their average areas, and in ascending order of the ID's if there is a tie.

Sample Input:

10
6666 5551 5552 1 7777 1 100
1234 5678 9012 1 0002 2 300
8888 -1 -1 0 1 1000
2468 0001 0004 1 2222 1 500
7777 6666 -1 0 2 300
3721 -1 -1 1 2333 2 150
9012 -1 -1 3 1236 1235 1234 1 100
1235 5678 9012 0 1 50
2222 1236 2468 2 6661 6662 1 300
2333 -1 3721 3 6661 6662 6663 1 100

Sample Output:

3
8888 1 1.000 1000.000
0001 15 0.600 100.000
5551 4 0.750 100.000

C++:

/*
 @Date    : 2018-02-28 10:11:53
 @Author  : 酸饺子 (changzheng300@foxmail.com)
 @Link    : https://github.com/SourDumplings
 @Version : $Id$
*/

/*
https://www.patest.cn/contests/pat-a-practise/1114
 */

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <memory>
#include <queue>
#include <set>

using namespace std;

static const int MAXN = 10001;
struct Person
{
    int id;
    int father, mother;
    set<int> children;
    double m_estate, area;
    Person(int id_, int f_, int m_): id(id_), father(f_), mother(m_),
        m_estate(0.0), area(0.0) {}
};
static shared_ptr<Person> data[MAXN];
static int N;
struct Family
{
    set<int> members;
    int smallest_id;
    Family(): area(0.0), sets(0.0) {}
    double area;
    double sets;
    double get_avg_area() const { return area / members.size(); }
    double get_avg_sets() const { return sets / members.size(); }
};
static vector<Family> families;
static bool checked[MAXN];

void add_members(Family &family, int ancestor)
{
    queue<int> Q;
    Q.push(ancestor);
    checked[ancestor] = true;
    while (!Q.empty())
    {
        int p = Q.front();
        Q.pop();
        family.area += data[p]->area;
        family.sets += data[p]->m_estate;
        family.members.insert(p);
        if (data[p]->father != -1 && !checked[data[p]->father])
        {
            checked[data[p]->father] = true;
            Q.push(data[p]->father);
        }
        if (data[p]->mother != -1 && !checked[data[p]->mother])
        {
            checked[data[p]->mother] = true;
            Q.push(data[p]->mother);
        }
        if (!data[p]->children.empty())
        {
            for (auto c : data[p]->children)
            {
                if (!checked[c])
                {
                    Q.push(c);
                    checked[c] = true;
                }
            }
        }
    }
    family.smallest_id = *family.members.begin();
    return;
}

bool cmp(const Family &f1, const Family &f2)
{
    if (f1.get_avg_area() == f2.get_avg_area())
        return f1.smallest_id < f2.smallest_id;
    return f1.get_avg_area() > f2.get_avg_area();
}

void read_person_data(int id)
{
    int f, m, k, c;
    scanf("%d %d", &f, &m);
    if (data[id] == nullptr) data[id] = make_shared<Person>(id, f, m);
    else
    {
        data[id]->father = f;
        data[id]->mother = m;
    }
    if (f != -1)
    {
        if (data[f] == nullptr) data[f] = make_shared<Person>(f, -1, -1);
        data[f]->children.insert(id);
    }
    if (m != -1)
    {
        if (data[m] == nullptr) data[m] = make_shared<Person>(m, -1, -1);
        data[m]->children.insert(id);
    }
    scanf("%d", &k);
    for (int i = 0; i != k; ++i)
    {
        scanf("%d", &c);
        data[id]->children.insert(c);
        if (data[c] == nullptr) data[c] = make_shared<Person>(c, id, -1);
        else if (data[c]->father == -1 && data[c]->mother != id)
            data[c]->father = id;
        else if (data[c]->mother == -1 && data[c]->father != id)
            data[c]->mother = id;
    }
    scanf("%lf %lf", &data[id]->m_estate, &data[id]->area);
    return;
}

int main(int argc, char const *argv[])
{
    scanf("%d", &N);
    fill(data, data + MAXN, nullptr);
    int id;
    for (int i = 0; i != N; ++i)
    {
        scanf("%d", &id);
        read_person_data(id);
    }
    fill(checked, checked + MAXN, false);
    for (int i = 0; i != MAXN; ++i)
    {
        if (!checked[i] && data[i] != nullptr)
        {
            families.push_back(Family());
            add_members(families.back(), i);
        }
    }
    sort(families.begin(), families.end(), cmp);
    printf("%d\n", families.size());
    for (auto &f : families)
        printf("%04d %d %.3f %.3f\n", f.smallest_id, f.members.size(),
               f.get_avg_sets(), f.get_avg_area());
    return 0;
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值