带权并查集

【带权并查集】理论和应用 这篇文章主要讲解带权并查集的理论、设计和实践。 理论 并查集本质 这和以往的并查集模型不太一样。并查集的数据结构使用数组实现时,那么数据结构的本质的是一个含有多棵树的森林。下图是普通并查集的连接情况。 并查集连接方式 每一颗树本身代表其所有结点是在同一集合内,连接整个集合是通过数组的下标代表当前结点的序号,相应数组的值代表其父结点的序号的方式,这样的连接不带有其他关系 带权... 阅读详情

以前写过带权并查集的题目,自己琢磨半天判断了很多情况,最后终于能过题了,但是写法之麻烦实在是没法保证再写一次也不会出错。看网上的博客才发现能够有简单许多的方法来搞定带权并查集。

首先就是获取祖先的函数,这个函数中与普通的并查集唯一的不同之处就是更新 dis 数组的部分,dis 中存的为该点到其祖先的距离。

int get_root(int x)
{
    if(father[x] == x) return x;

    int root = get_root(father[x]);
    //回溯时将原来的父亲到祖先的距离加上,那么就可以得到该点到祖先的距离
    dis[x] = dis[x] + dis[father[x]];
    return father[x] = root;    //路径压缩
}

那么接下来就是重要的合并以及判断冲突的部分了。

a    →    ra

↓x           ↓y

b    →    rb

如图,ra 为 a 的祖先,rb 为 b 的祖先,那么 a 到 ra 的距离为 dis[a],b 到 rb 的距离为 dis[b]。

如果 ra 不等于 rb ,则表示 a 与 b 的距离是不确定的,需要通过给定的距离来建立 a 与 b 之间的关系,现在得知 a 与 b 之间的距离是 x ,由向量中的知识我们可以得到,ra 与 rb 之间的距离 y = -dis[a] + x + dis[b],然后将 a 与 b 合并到一个集合,即 father[ra] = rb,这样 a 与 b 之间的关系, a 与(b所在的集合中的其他点)之间的关系以及 b 与(a所在的集合中的其他点)之间的关系就建立完成了。

a    →    ra == rb

↓x        ↗      

b

如果 ra 等于 rb,那么就表示 a 与 b 之间的关系已经确定了,这时就需要判断是否有冲突了。现在得知 a 与 b 之间的距离为 x,那么只需要判断 x 等不等于 dis[a] - dis[b] 即可,若等于则皆大欢喜,若不等于则必然是产生冲突了。

一道模板题:HDU-3047

代码:(输入不能cin,会超时...醉了)

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <bitset>
using namespace std;

typedef long long ll;
#define int ll
#define INF 0x3f3f3f3f3f3f3f3f
#define MAXM 100000 + 10
#define MAXN 50000 + 10
const ll mod = 1e9 + 7;
#define P pair<int, int>
#define fir first
#define sec second

int n, m;
int father[MAXN], dis[MAXN];
int ans;

int get_root(int x)
{
    if(father[x] == x) return x;

    int root = get_root(father[x]);
    dis[x] += dis[father[x]];
    return father[x] = root;
}

signed main()
{
    while(cin >> n >> m) {
        memset(dis, 0, sizeof(dis));
        ans = 0;
        for(int i = 0; i < MAXN; i ++) father[i] = i;

        for(int i = 0; i < m; i ++) {
            int a, b, x; //cin >> a >> b >> x;
            scanf("%lld %lld %lld", &a, &b, &x);
            int ra = get_root(a);
            int rb = get_root(b);
            if(ra == rb) {
                if(dis[a] - dis[b] != x)
                    ans ++;
            }
            else {
                father[ra] = rb;
                dis[ra] = -dis[a] + x + dis[b];
            }
        }
        cout << ans << endl;
    }
}

/*

The WAM is F**KING interesting .

*/

同样,带权并查集也可以解决种类并查集的问题,在距离数组中取个mod就好了,那就省去了开几倍数组的麻烦,而且还能解决种类数很多的情况。

经典种类并查集:食物链

代码:

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <bitset>
using namespace std;

typedef long long ll;
#define int ll
#define INF 0x3f3f3f3f3f3f3f3f
#define MAXM 100000 + 10
#define MAXN 50000 + 10
const ll mod = 1e9 + 7;
#define P pair<int, int>
#define fir first
#define sec second

int n, m;
int father[MAXN], kind[MAXN];
int ans;

int get_root(int x)
{
    if(father[x] == x) return x;

    int root = get_root(father[x]);
    kind[x] = (kind[x] + kind[father[x]]) % 3;
    return father[x] = root;
}

signed main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i ++) father[i] = i;

    for(int i = 0; i < m; i ++) {
        int x, a, b; cin >> x >> a >> b;
        x --;
        if(a > n || b > n) {
            ans ++;
            continue;
        }
        int ra = get_root(a);
        int rb = get_root(b);
        if(ra == rb) {
            if(x != (kind[a] - kind[b] + 3) % 3)
                ans ++;
        }
        else {
            father[ra] = rb;
            kind[ra] = (kind[b] - kind[a] + x + 3) % 3;
        }
    }
    cout << ans << endl;
}

/*

The WAM is F**KING interesting .

*/

 

并查集及带权并查集 若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。xxx和yyy是亲戚,yyy和zzz是亲戚,那么xxx和zzz也是亲戚。如果xxxyyy是亲戚,那么xxx的亲戚都是yyy的亲戚,yyy的亲戚也都是xxx的亲戚。带权并查集是一种用于解决带权无向图中连通性问题的数据结构。它是并查集的扩展,包括点带权和边带权。它除了记录元素之间的关系外,还可以记录元素的权重。在点带权中,我们使用n。 阅读详情

相关推荐

利用Arcgis提取nc数据并计算区域年均温

1.下载数据。2.解压数据至不含中文的路径中。打开工具箱中的多维分析工具-创建NetCDF栅格图层,导入数据。3.打开工具箱中的数据管理工具-图层和表视图-创建栅格图层,导入数据,对输出数据进行命名,得到月均温栅格数据。4.选择工具箱-Spatial Analyst工具(空间分析工具)-地图代数-栅格计算器,计算全国一年年均温。​5.将其导出为.tif格式数据,方便后期使用。6.选择工具箱-Spatial Analyst工具(空间分析工具)-区域分析--以表格显示分区统计,得到分区域的气温数据。

什么都学亿点点的博客 7992

卷积神经网络

深度神经网路已经在语音识别,图像识别等领域取得前所未有的成功。本人在多年之前也曾接触过神经网络。本系列文章主要记录自己对深度神经网络的一些学习心得。 第二篇,讲讲经典的卷积神经网络。我不打算详细描述卷积神经网络的生物学运行机理,因为网络上有太多的教程可以参考。这里,主要描述其数学上的计算过程,也就是如何自己编程去实现的问题。 1. 概述 ...

weixin_34061555的博客 380

AUTOSAR CAN通信全过程

首先,从AUTOSAR架构上来说,一个完整的CAN通信的过程涉及到了包括硬件、AUTOSAR中间件和上层应用层软件;在硬件部分来说,涉及到的是CAN 总线和CAN的收发器;软件部分的话,涉及到的概念是MCAL(微控制器抽象层)、BSW(基础软件层)、RTE(实时运行环境)、APPL(应用层)等;其中MCAL部分用到了通信驱动模块,而BSW部分使用到了通信服务模块和通信硬件抽象模块;由于笔者是做MCAL和BSW的,至于应用层部分的知识就暂且不具体介绍了;

xxdw1992的博客 6253

UVA11987(带权并查集的删除操作)

Problem A Almost Union-Find I hope you know the beautiful Union-Find structure. In this problem, you're to implement something similar, but not identical. The data structure you need to write is

代码艺术的道与术 2580

【机械臂算法】基于最小惯性参数集的动力学辨识仿真实践

本文深入探讨了机械臂动力学参数辨识的核心挑战与解决方案,重点阐述了基于最小惯性参数集的理论与方法。通过分析PUMA560实例,详细介绍了利用QR分解法或符号推导法获取可辨识参数集,并系统讲解了从激励轨迹设计、仿真数据采集、线性系统求解到模型验证的完整实践流程,为高精度动力学建模与控制奠定了坚实基础。

weixin_29054399的博客 376

Class AB OPA STB仿真相位异常:从corner case到碰撞电离的排查与规避

本文深入分析了Class AB运算放大器(OPA)在STB稳定性仿真中,特定工艺角(corner case)下出现相位从0°开始的异常现象。排查发现,其根本原因在于高Vds引发的碰撞电离效应,通过衬底和电源网络引入了隐藏的正反馈通路。文章对比了修改衬底连接与优化电路降低Vds两种解决方案,并基于工程实践推荐了代价更小、兼容性更好的电路优化方案,成功规避了问题并完成流片验证。

grape的博客 636

基本数据结构:并查集(路径压缩与按秩合并)

本文重点介绍了并查集的实现与它的两种优化方式:路径压缩与按秩合并。

yuhaomogui的博客 1886

RK3568平台开发系列讲解:UBOOT详细介绍

U-boot是一款广泛使用的开源引导加载程序,支持多种嵌入式操作系统和处理器架构。其主要功能包括系统上电时的硬件初始化、引导操作系统内核等。U-boot的引导流程通常包括Boot Code、idbloader.img、uboot.img、boot.img和rootfs.img等步骤。启动U-boot时,通过Debug串口连接板卡,按下ctrl+c键可进入U-Boot命令行模式。U-boot启动过程中会执行一系列初始化操作,如打印系统信息、初始化内存、加载内核设备树、初始化I2C、PMIC电源芯片、DRM框架

内核笔记 808

2026年AI编程工具实测:谁能真正解放前端开发者?

从简单的代码补全到理解整个项目上下文,AI编程工具正经历从“辅助编码”到“自主执行”的进化。原理上,它们依赖大模型对自然语言与代码映射的深度理解,并结合上下文感知、跨文件分析等能力,实现从描述需求到生成完整功能模块的跨越。技术价值体现在大幅提升前端开发效率,减少重复劳动,甚至重塑开发工作流。在后台管理、复杂交互页面、设计稿还原等典型前端场景中,选对工具尤为关键。本文基于真实项目体验,对GitHub Copilot、Cursor、通义灵码、Trae等主流工具进行对比,剖析其在前端开发中的优势与不足,并给出场景

weixin_34216107的博客 414

31、贝叶斯认知建模与隐马尔可夫模型:理论与应用

本文探讨了贝叶斯认知建模与隐马尔可夫模型(HMM)的理论基础及其在认知科学和神经科学中的应用。重点介绍了贝叶斯定理和HMM的基本原理,并结合实际案例,如情绪识别系统和脑机接口(BCI),展示了它们在处理复杂认知任务中的强大能力。文章还讨论了贝叶斯-HMM模型的技术细节、优势与局限性,以及未来的发展前景。

meat5的博客 141

Android Binder的两三事--基于Android14源码

Android14-Framework-Binder

保持专注,保持热爱 1140

POJ_1984_(带权并查集)

POJ 1984 自己审题问题极其严重 1.忽略了该题询问i行可能询问多次, 2.忽略了给出询问行不是按顺序的排序的,我以为是按顺序, 没有想出怎么用带权并查集做 根据给出的东南西北来维护dx横坐标到根节点距离 dy纵坐标到根节点距离, 路径压缩的时候dx dy一起压缩就行,主要是合并的时候根据题目给出的东南西北来确定dx dy 合并根节点 还是rala[ra] = rala[b] + s - ...

_llc的博客 291

嵌入式工程师必学(9):USB 3.0协议理解

USB3.0和USB2.0相比,在线缆上从4根线(Vbus、GND、D+、D-)变为了8根线(Vbus、GND、D+、D-、SSRX+\SSRX-\SSTX+\SSTX-),可见增加的4根线都是和超速相关的,新增加的超速有两类,分别为:超速Gen1(5.0Gbps),超速+Gen2(10Gbps),还兼容USB2.0的3类速率:low-speed(1.5Mbps),full-speed(12Mbps),andhigh-speed(480Mbps)。从设计可以看出,USB3....

码农17年的博客 1万+

带权并查集初探及例题解析

带权并查集是在普通并查集的基础上进行了扩展。普通并查集主要用于处理不相交集合的合并与查询问题,它可以高效地判断两个元素是否属于同一个集合,以及合并两个不同的集合。带权并查集在每个元素上额外维护了一个权值,这个权值可以表示元素之间的某种关系,比如距离、差值等。通过这些权值,我们可以在合并和查询操作的过程中获取更多关于元素之间关系的信息。带权并查集非常灵活,同时也学习成本也较高,作者在初看时也云里雾里,不过通过画图理清各个元素和树之间的逻辑关系,再到理解逻辑到内存上的映射关系,就能略懂一二了。

2404_88241585的博客 987

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

带权并查集算法教程

带权并查集算法教程,带你轻松学习带权并查集

pursuit的博客 1387

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

带权并查集 详解

简介 带权并查集与普通并查集的区别在于,其每条边/每个点都有权值。因此,我们需要额外用一个数组来维护每个点 xxx 到其当前祖先 faxfa_xfax​ 的权值和,并在路径压缩的时候维护。 直接说可能较难理解,于是下面是一道例题。 P1169 Description 传送门 Solution 考虑对于每个点 xxx,维护其到其祖先 faxfa_xfax​ 的距离 depxdep_xdepx​,并对于每个并查集的根维护连通块大小 sizsizsiz。 对于一个 M 操作,令涉及到的战舰分别为 x,yx,yx,

Cherrt的博客 2705

【数据结构】带权并查集

带权并查集的应用

2401_87820834的博客 1567

带权并查集 & 种类并查集

带权并查集就是在维护集合关系的树中添加边权的并查集,这样做可以维护更多的信息。 在对并查集进行路径压缩和合并操作时,这些权值具有一定属性,即可将他们与父节点的关系,变化为与所在树的根结点关系。 也就是说,权值代表着**当前节点与父节点的某种关系(即使路径压缩了也是这样)**,通过两者关系,一般的并查集,维护的是具有连通性、传递性的关系,例如**亲戚的亲戚是亲戚**。但是,有时候,我们要维护另一种关系:**敌人的敌人是朋友**。种类并查集就是为了解决这个问题而也可以将同一棵树下两个节点的关系表示出来。

SZTU_ZJB的博客 1991

【并查集】 带权并查集详解

一.引入 并查集实际上是一颗由若干个树构成的森林,而如果还需要储存边的权值,则需要额外用一个数组d记录每个结点和其父节点的权值 这个思路其实很简单,但是因为路径压缩会改变点与点的连接关系,路径压缩后,点的父节点变为了根节点,所以需要更新d数组 二.查询函数写法 更新权值在查询操作的同时进行 int root_find(int x){ if(x==pre[x]) return x; int root=root_find(pre[x]); d[x]+=d[pre[...

Qiuker_jl的博客 2488

算法-带权并查集

带权并查集是在普通并查集的基础上为每一个节点赋予了一个权值,这个权值可以表示当前节点和根节点的关系,距离或者其他信息,注意这个节点权值代表的意义有可能根据题意的不同而发生变化,所以不能生搬硬套,要理解其代表的不同含义。注意:在普通并查集里,我们用到了路径压缩,即在查找的过程中将在同一集合中的所有节点都实现了让其指向根节点的操作,所以在带权并查集的查找和合并的过程中,我们不仅要维护这个并查集,也要维护对应节点权值的变化。

TAO2152726799的博客 838

带权并查集理解

前言:这几天做了几个带权并查集的问题,看了网上的大量博客,也有自己的一些理解,特地总结一下。 文章目录回顾带权并查集带权并查集题型特点。例题:Bug's Life 回顾 理清理论的发展历史有助于了解理论,因此我们先回顾一下普通的并查集。戳这里.和这里,感谢博主带我入门 这里有几个值得注意的地方(也是个人做题中踩过的坑)。 在包含路径压缩算法的, 调用find_father(x)后,x所在集合...

Wangpeiyi9979的博客 599
上一篇: 洛谷P1113 杂务 (拓扑排序求最长路)
下一篇: 洛谷P1726 上白泽慧音 (强连通分量 Korasaju算法)
ttoobne
博客等级 码龄9年 13粉丝 59原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值