带权并查集

本文介绍了带权并查集的概念,并通过HDU3047.ZjnuStadium这个模板题详细展示了带权并查集的代码实现,包括路径压缩和合并操作。在解决该问题中,当尝试将两个节点合并时,会更新节点间的权值,用于记录路径信息。最终,算法统计了不满足权值条件的边的数量。
摘要由CSDN通过智能技术生成

原理
带权并查集和朴素并查集不同的是,带权并查集每个节点到根节点之间有一个权值,因此在路径压缩和合并操作时会有区别,具体代码通过下面的一个模板题给出.

HDU3047.Zjnu Stadium

代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#define ll long long
using namespace std;
const int N=1e5+10
int n,m,par[N],val[N];

void init(){
    for(int i=1;i<=n;i++){
        par[i]=i;
        val[i]=0;
    }
}

int find(int x){
    if(par[x]==x)
        return x;
    int p=par[x];
    par[x]=find(par[x]); //路径压缩
    val[x]+=val[p]; //更新x的权值
    return par[x];
}

void unite(int x,int y,int w){ //合并操作
    int xr=find(x),yr=find(y);
    par[x]=yr;
    par[xr]=yr;
    val[xr]=val[y]+w-val[x]; //更新节点权值
    val[x]=val[y]+w;

}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        int ans=0,x,y,w;
        init();
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&x,&y,&w);
            int r1=find(x),r2=find(y);
            if(r1!=r2)
                unite(y,x,w);
            else{
                if(val[y]!=val[x]+w)
                    ans++;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值