pta1114麻烦的并查集

本文介绍了一个使用并查集算法解决家族财产合并与计算平均财产情况的问题。通过输入人员的家庭关系和财产数据,算法将家庭合并为家族,计算每个家族的成员数量和平均房产数量及面积。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:给一个数n,之后说明n个人财产情况,格式为  人员编号  父编号  母编号  孩子个数  数个孩子编号---  房产数量   房产面积

虽然让求出有多少个家族及家族平均财产情况,输出为 

家族编号最小成员  家族人数  平均房山数(三位小数) 平均面积(三位小时)

之前显是在输入上卡了很久double和float的输入均为%f不是%lf!!

输出也要注意

 printf("%04d %d %.3lf %.3lf\n", v2[i].n, v2[i].num, v2[i].s, v2[i].a);

还有初始化的问题

struct node {
    int num;
    int n;
    double s;
    float a;
    node() {   //这样可以对新建的进行初始化
        num = 1;
        s = 0;
        a = 0;
    }

}v[10005];

思路问题,乍一看知道是并查集,但又比较麻烦,显示把家族合并,然后把财产先归到个人,最后遍历,把财产加给那个最小的成员(也就是祖先),最后计算平均排序

int zu[10005];
int pan[10005];

struct node {
    int num;
    int n;
    double s;
    float a;
    node() {   //这样可以对新建的进行初始化
        num = 1;
        s = 0;
        a = 0;
    }

}v[10005];   //这样创建可以创建一系列已经被初始化的node

int qiuzu(int a)
{
    if (zu[a] != a)
        return zu[a] = qiuzu(zu[a]);
    else
        return a;
}

void marge(int a, int b)
{
    int p1 = qiuzu(a);
    int p2 = qiuzu(b);
    if (p1 < p2)   //把祖先定为最小的那个
        zu[p2] = p1;
    else
        zu[p1] = p2;
}

bool cmp(node a, node b)
{
    if (a.a > b.a)
        return true;
    if (a.a == b.a&&a.n < b.n)
        return true;
    return false;
}

int main(void)
{
    int n, i, j;
    scanf("%d", &n);
    for (i = 0;i < 10000;i++)
        zu[i] = i;
    for (i = 0;i < n;i++)
    {
        int a, b, c, mi;
        scanf("%d%d%d", &a, &b, &c);   //接受自己和爸妈
        pan[a] = 1;   //证明该人存在
        if (b != -1)  //爸妈存在则合并家庭
        {
            marge(a, b); 
            pan[b] = 1;
        }
        if (c != -1)
        {
            marge(a, c);
            pan[c] = 1;
        }
        int n2;
        scanf("%d", &n2);
        for (j = 0;j < n2;j++)  //接受孩子并合并孩子
        {
            int d;
            scanf("%d", &d);
            marge(a, d);
            pan[d] = 1;
        }
        scanf("%f%f", &v[a].s, &v[a].a);   //把所有房产算到本人头上,这里卡了一下,之前不小心写成%lf就乱码
    }
    set<int> s;
    for (i = 9999;i >= 0;i--)  
    {
        if (pan[i] == 1)
        {
            int x = qiuzu(i); 
            s.insert(x);   //把最小的家族人员打入
            if (x != i)   //从后向前遍历,把所有的财产算到祖先头上(祖先数最小的那个
            {
                v[x].num += v[i].num;  //就算该人财产为0,单因为已经初始化,所以不会乱码
                v[x].s += v[i].s;
                v[x].a += v[i].a;
            }
        }
    }
    set<int>::iterator it;
    vector<node> v2;
    for (it = s.begin();it != s.end();it++)   //遍历家族,并求出人均财产
    {
        v[*it].s = v[*it].s / v[*it].num;
        v[*it].a = v[*it].a / v[*it].num;
        v[*it].n = *it;
        v2.push_back(v[*it]);
    }
    sort(v2.begin(), v2.end(), cmp);
    printf("%d\n", v2.size());
    for (i = 0;i < v2.size();i++)
    {
        printf("%04d %d %.3lf %.3lf\n", v2[i].n, v2[i].num, v2[i].s, v2[i].a);  //注意输出格式
    }
    return 0;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值