并查集扩展

在这里插入图片描述
简单并查集。要注意的是,像这种结点带有很多信息,要求对结点信息按连通分量进行汇总的并查集,可以不要在union操作里进行,而选择在进行完所有合并后,对所有结点遍历进行汇总。这样不容易出错。

#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std ;
#define MAX 10000///最大范围
int f[MAX],vis[MAX]={0};///f用于记录并查集每个点的父亲 vis记录是否访问过
struct family///家族结构体
{
    int id,people ;
    double area,house ;//area是占地面积  house是房产套数
};
family person[MAX],*ans[MAX];//person记录相应id的家族信息,ans是个指针数组,记录答案
int ant = 0;//ans数组下标
bool cmp(family *a,family *b)///排序比较函数
{
    if((a->area / a->people) == (b->area / b->people))
        return a->id < b->id;
    return (a->area / a->people) > (b->area / b->people);
}
void init()///初始化f
{
    for(int i = 0;i < MAX;i ++)
        f[i] = i;
}
int getf(int x)///get father
{
    if(x != f[x])f[x] = getf(f[x]);
    return f[x];
}
void marriage(int x , int y)///merge合并
{
    int xx,yy;
    xx = getf(x) ;
    yy = getf(y) ;
    if(xx != yy)
    {
        if(xx > yy)///方便找到最小id  让id小的当父亲那么找到的id与父亲相等的点最小id就是自己
        {
            f[xx] = yy;
        }
        else f[yy] = xx;
    }
}

int main()
{
    int n,id,mother,father,k,child;
    cin>>n;
    init();
    for(int i = 0;i < n;i ++)
    {
        cin>>id>>father>>mother;
        vis[id] = 1 ;
        if(mother!=-1) {marriage(id,mother);vis[mother]=1;}///假如父亲访问过那么他肯定已经和id合并过 母亲也是
        if(father!=-1) {marriage(id,father);vis[father]=1;}
        cin>>k;
        for(int j = 0;j < k;j ++)
        {
            cin>>child;
            if(child!=-1)
            {
                marriage(id,child);
                vis[child] = 1;
            }
        }
        cin>>person[id].house>>person[id].area;///id作为下标方便寻找
    }
    for(int i = 0;i < MAX;i ++)
    {
        if(!vis[i])continue;
        int f = getf(i);
        if(f == i)
        {
            person[i].people ++;
            ans[ant ++] = &person[i];
            person[i].id = i;///需要注明
            continue;
        }
        person[f].people ++;
        person[f].house += person[i].house;
        person[f].area += person[i].area;
    }
    sort(ans,ans + ant,cmp);
    cout<<ant<<endl;
    for(int i = 0;i < ant;i ++)
        printf("%04d %d %.3f %.3f\n",ans[i]->id,ans[i]->people,ans[i]->house/ans[i]->people,ans[i]->area/ans[i]->people);
    return 0 ;
}![
发布了73 篇原创文章 · 获赞 3 · 访问量 3494

猜你喜欢

转载自blog.csdn.net/qq_42021845/article/details/104089230
今日推荐