并查集

本文深入探讨了并查集算法的实现细节及其应用场景,通过一个具体的编程实例展示了如何使用并查集来解决复杂的数据结构问题。文章首先介绍了并查集的基本概念和操作,接着详细解释了如何通过并查集维护节点之间的关系,并在此基础上进行有效的数据聚合计算。

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

这里写图片描述
代码:

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<set>

using namespace std;

int fa[10090];
int minn[10090];
int nump[10090];
int numh[10090];
int nums[10090];
int have[10090];

int n;
int fin(int y){
    return fa[y]==y?y:fa[y]=fin(fa[y]);
} 
void uni(int a,int b){
    int f1=fin(a),f2=fin(b);
    if(f1==f2)return;
    fa[f1]=f2;
    minn[f2]=min(minn[f2],minn[f1]);
    nump[f2]+=nump[f1];
    numh[f2]+=numh[f1];
    nums[f2]+=nums[f1];
}
struct edge{
    int minn,nump,nums,numh;
}e[10000];int now=0;
bool cmp(edge a,edge b){
    if(a.nums*1.0/a.nump!=b.nums*1.0/b.nump)
        return a.nums*1.0/a.nump>b.nums*1.0/b.nump;
    return a.minn<b.minn;
}
int main(){
    memset(minn,90,sizeof(minn));
    for(int i=0;i<=10000;i++)fa[i]=i,minn[i]=i,nump[i]=1;
    cin>>n;
    for(int i=1;i<=n;i++){
        int a,b,c;int k;
        scanf("%d%d%d%d",&a,&b,&c,&k);have[a]=1;
        if(b!=-1)uni(a,b),have[b]=1;
        if(c!=-1)uni(a,c),have[c]=1;
        while(k--){int tmp;
            scanf("%d",&tmp);
            have[tmp]=1;
            uni(a,tmp);
        }
        int u,v;scanf("%d%d",&u,&v);
        numh[fin(a)]+=u;
        nums[fin(a)]+=v;
    }
    int co=0;
    for(int i=0;i<=10000;i++)if(have[i]&&fa[i]==i)co++;
    printf("%d\n",co);
    for(int i=0;i<=10000;i++)if(have[i]&&fa[i]==i){
        e[++now].minn=minn[i];e[now].nump=nump[i];
        e[now].nums=nums[i];e[now].numh=numh[i];
    }
    sort(e+1,e+1+now,cmp);
    for(int i=1;i<=now;i++){
        printf("%04d %d %.3f %.3f\n",e[i].minn,e[i].nump,e[i].numh*1.0/e[i].nump,e[i].nums*1.0/e[i].nump);
    }
}

样例:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值