并查集及其应用

article/2025/8/27 2:52:52

并查集的基本操作:

1.合并两个集合

2.查询两个元素的祖宗节点

扩展:

1.记录每个集合的大小 将集合大小绑定到代表元素节点上 就是并查集的思想 (不是每个元素都是正确的 但是代表元素是正确的)

2.记录每个点到根节点的距离 绑定到每个元素身上 因为每个元素到根节点的距离都是不一样的

边带权的并查集

边带权并查集,顾名思义,就是各个结点之间带有权值的并查集,在查询和合并时可以维护结点之间的权值。边带权并查集可以用于统计每个节点到树根之间路径上的一些信息。

扩展域并查集

扩展域用以维护较抽象的对象之间的逻辑关系,由于有点抽象,所以理解起来有点费劲。

扩展域将数据之间的关系分类,将对象之间不同的关系种类分开讨论,并在这些数据之间建立联系。

假定现在要维护要k类集合 如果k不大两个都行  k大就选边带权


 

1.格子游戏

信息学奥赛一本通(C++版)在线评测系统

题意问第一次连成圈是什么时候

分析一下形成环的条件就是在连边的时候 边的两个端点已经在一个集合里面了 直接并查集

细节:把两位坐标转换为一维 (x,y)-->x*n+y x y从0开始

#include <bits/stdc++.h>
using namespace std;
const int N=40010;
int n,m;
int p[N];
int find(int x)
{if(p[x]!=x) p[x]=find(p[x]);return p[x];
}
int get(int x,int y)
{return x*n+y;
}
int main()
{cin>>n>>m;for(int i=0;i<n*n;i++)p[i]=i;int res=0;for(int i=1;i<=m;i++){int x,y;char d;cin>>x>>y>>d;x--,y--;int a=get(x,y);int b;if(d=='D'){b=get(x+1,y);}else b=get(x,y+1);int pa=find(a),pb=find(b);if(pa==pb){res=i;break;}p[pa]=pb;}if(!res) puts("draw");else cout<<res<<endl;return 0;
}

2.搭配购买

信息学奥赛一本通(C++版)在线评测系统

分析过后就可以知道我们每次只能去买一组云 然后会得到一个体积和价值 那么这不就是01背包吗

让后用并查集维护好每一组就ok了

看起来像有依赖的背包问题 但是不是 因为这里要买一个物品就要把全部物品都买了 而有依赖的背包问题是要买后者就要买前者这种条件

#include <bits/stdc++.h>
using namespace std;
const int N=10010;
int n,m,vol;
int v[N],w[N];
int p[N];
int f[N];
int find(int x)
{if(p[x]!=x) p[x]=find(p[x]);return p[x];
}
int main()
{cin>>n>>m>>vol;for(int i=1;i<=n;i++)p[i]=i;for(int i=1;i<=n;i++) cin>>v[i]>>w[i];while(m--){int a,b;cin>>a>>b;int pa=find(a),pb=find(b);if(pa!=pb){v[pb]+=v[pa];w[pb]+=w[pa];p[pa]=pb;}}for(int i=1;i<=n;i++)if(p[i]==i){for(int j=vol;j>=v[i];j--)f[j]=max(f[j],f[j-v[i]]+w[i]);}cout<<f[vol]<<endl;return 0;
}

3.程序自动分析

237. 程序自动分析 - AcWing题库

由于数据范围很大 但是操作数很小 所以要离散化

1.约束条件的顺序是无所谓的 所以可以先考虑所有的相等元素 这里是不会有矛盾的

2.再去考虑所有不等的元素 如果不等的元素已经在一个集合了 那肯定是矛盾的

并查集维护就行了

#include <bits/stdc++.h>
using namespace std;
const int N=2000010;
int n,m;
int p[N];
unordered_map<int,int> mp;
struct node
{int x,y;int e;
}query[N];
int find(int x)
{if(p[x]!=x) p[x]=find(p[x]);return p[x];
}
int get(int x)
{if(mp.count(x)==0) mp[x]=++n;return mp[x];
}
int main()
{int t;cin>>t;while(t--){n=0;mp.clear();cin>>m;for(int i=0;i<m;i++){int x,y,e;cin>>x>>y>>e;query[i]={get(x),get(y),e};}for(int i=1;i<=n;i++) p[i]=i;for(int i=0;i<m;i++){if(query[i].e==1){int pa=find(query[i].x),pb=find(query[i].y);p[pa]=pb;}}bool has_conflict=false;for(int i=0;i<m;i++)if(query[i].e==0){int pa=find(query[i].x),pb=find(query[i].y);if(pa==pb){has_conflict=true;break;}}if(has_conflict) puts("NO");else puts("YES");}return 0;
}

4.奇偶游戏

239. 奇偶游戏 - AcWing题库

用前缀和的思想去思考 s[ l ~ r ]中有奇数个1代表 s[ r ] - s[ l - 1 ] 中有奇数个1 代表s[r]和s[l-1]奇偶性不同    偶数个1的话就是s[r]和s[l-1]奇偶性相同

但是奇偶性无矛盾一定可以推出来该问题无矛盾?

令a[i]=| s[i]-s[i-1] | 一定可以构造出来一个无矛盾的方案 所以是等价的

带边权并查集

 代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10;
int p[N],d[N];//s表示集合的长度,d表示每个点到根节点的距离
int n,m;
unordered_map<int,int> ha;
int get(int x)
{if(!ha.count(x)) ha[x]=++n;return ha[x];
}
int find(int x)
{if(p[x]!=x) {int root=find(p[x]);d[x]^=d[p[x]];//更新路径长其他的值p[x]=root;}return p[x];
}
int main()
{cin>>n>>m;n=0;int res=m;for(int i=0;i<N;i++) p[i]=i;//初始化for(int i=1;i<=m;i++){int a,b;string type;cin>>a>>b>>type;a=get(a-1),b=get(b);//获取离散化后的值int t=0;if(type=="odd") t=1;//假如是奇数int pa=find(a),pb=find(b);if(pa==pb)//假如在一个集合{if((d[a]^d[b])!=t)//假如跟t不同类{res=i-1;break;}}else//反之不在一个集合就合并{p[pa]=pb;d[pa]=d[a]^d[b]^t;//合并到同一类中}}cout<<res<<endl;return 0;
}

扩展域并查集

 

#include<bits/stdc++.h>
using namespace std;
const int N=2e4+10,M=N/2;//M是分界线在0-M是偶数,大于M是奇数
int p[N],d[N];//s表示集合的长度,d表示每个点到根节点的距离
int n,m;
unordered_map<int,int> ha;
int get(int x)
{if(!ha.count(x)) ha[x]=++n;return ha[x];
}
int find(int x)
{if(p[x]!=x) p[x]=find(p[x]);return p[x];
}
int main()
{cin>>n>>m;n=0;int res=m;for(int i=0;i<N;i++) p[i]=i;//初始化for(int i=1;i<=m;i++){int a,b;string type;cin>>a>>b>>type;a=get(a-1),b=get(b);//获取离散化后的值int a1=find(a),a2=find(a+M),b1=find(b),b2=find(b+M);//获取a跟b的偶数和奇数情况if(type=="odd")//假如是奇数类型{if(a1==b1||a2==b2)//但是a跟b同类了{res=i-1;break;}p[a1]=b2;//反之把a的偶数合并到b的奇数p[a2]=b1;//反之把a的奇数合并到b的偶数}else//假如是偶数{if(a1==b2||a2==b1)//假如不同类{res=i-1;break;}p[a1]=b1;//把偶数合并到偶数里p[a2]=b2;//把奇数合并到奇数里}}cout<<res<<endl;return 0;
}

5.银河英雄传说

238. 银河英雄传说 - AcWing题库

题目的两个操作:1.合并集合 2.两点间距离 用并查集维护到根节点的距离就行了

1.让排头当根节点

2.d[pa]=size[pb]

3.size[pb]+=size[pa]

 

 

看到这里会不会有疑惑 就是说明明我是find完pa pb以后再将d[pa]=size[pb] size[pb]+=size[pa]的那为什么可以能维护每个点道根节点的距离的 也就是这段代码

        if(op[0]=='M'){int pa=find(a),pb=find(b);if(pa!=pb){d[pa]=s[pb];s[pb]+=s[pa];p[pa]=pb;}}

 其实呢更新每个点到根节点的距离是在查询的时候更新的

        else{int pa=find(a),pb=find(b);//这里更新的捏if(pa!=pb) puts("-1");else printf("%d\n",max(0,abs(d[a]-d[b])-1));}

完整代码 

#include <bits/stdc++.h>
using namespace std;
const int N=30010;
int n,m;
int p[N],s[N],d[N];
int find(int x)
{if(p[x]!=x){int root=find(p[x]);d[x]+=d[p[x]];p[x]=root;}return p[x];
}
int main()
{cin>>m;for(int i=1;i<=N;i++){p[i]=i;s[i]=1;}while(m--){char op[2];int a,b;cin>>op>>a>>b;if(op[0]=='M'){int pa=find(a),pb=find(b);if(pa!=pb){d[pa]=s[pb];s[pb]+=s[pa];p[pa]=pb;}}else{int pa=find(a),pb=find(b);if(pa!=pb) puts("-1");else printf("%d\n",max(0,abs(d[a]-d[b])-1));}}return 0;
}


http://chatgpt.dhexx.cn/article/YIymp8B8.shtml

相关文章

并查集(Union-Find) (图文详解)

文章目录 并查集基础知识定义C实现优化 精选算法题(Java实现)实现并查集交换字符串中的元素最长连续序列 - 字节面试常考连通网络的操作次数最大岛屿数量 (三种解法)省份数量冗余连接冗余连接Ⅱ情侣牵手(困难)移除最多的同行或同列石头等式方程的可满足性 结语 并查集基础知识 …

什么是 “并查集” ?

导语&#xff1a;并查集是一种精巧的算法&#xff0c;本身并不难理解&#xff0c;却很常用&#xff0c;在许多场景下都能找到并查集的身影。 本文作者封承成&#xff0c;年仅12岁&#xff0c;非常感谢他的投稿。 并查集是什么 并查集&#xff0c;是一种判断“远房亲戚”的算法。…

并查集(Disjoint Set)

目录 ❤️什么是并查集&#xff1f; &#x1f3b6;实现方法1 &#x1f414;实现方法2 &#x1f383;题目1 ❤️什么是并查集&#xff1f; 并查集是一种数据结构&#xff0c;用于处理一些不交集&#xff08;Disjoint sets&#xff0c;一系列没有重复元素的集合&#xff09;的…

并查集

参考 https://www.cnblogs.com/asdfknjhu/p/12515480.html https://www.bilibili.com/video/BV13t411v7Fs?p3 https://leetcode-cn.com/problems/number-of-provinces/solution/python-duo-tu-xiang-jie-bing-cha-ji-by-m-vjdr/ 一、基本概念 并查集是一种数据结构 并查集这…

并查集(详细解释+完整C语言代码)

目录 1概论 2.树的表现形式 3.代码实现 3.1创立集合 3.2合并 3.3查询 3.4路径压缩 第一个方法&#xff1a;查找时优化 第二个方法&#xff1a;合并时优化&#xff08;加权标记法&#xff09; 4.完整代码 4.1优化前 4.2优化后 1概论 并查集是一种十分精巧且实用的树形…

时间序列预测的一般步骤

一、ARIMA模型概述 ​​ ARMA模型就是AR和MA的简单结合&#xff0c;同时包含了历史数值项和错误项。由于AR和MA模型都对时间序列有平稳性要求&#xff0c;ARMA模型也存在这个限制&#xff0c;因此我们将其拓展到ARIMA模型&#xff0c;其可以解决非平稳性问题。引入的差分概念是…

时间序列预测算法总结

时间序列算法 time series data mining 主要包括decompose&#xff08;分析数据的各个成分&#xff0c;例如趋势&#xff0c;周期性&#xff09;&#xff0c;prediction&#xff08;预测未来的值&#xff09;&#xff0c;classification&#xff08;对有序数据序列的feature提…

基于深度学习的时间序列预测

# 技术黑板报 # 第十一期 推荐阅读时长&#xff1a;15min 前言 时间序列建模历来是学术和工业界的关键领域&#xff0c;比如用于气候建模、生物科学和医学等主题应用&#xff0c;零售业的商业决策和金融等。虽然传统的统计方法侧重于从领域专业知识层面提供参数模型&#xff0…

预测类问题中的时间序列预测模型

前言&#xff1a;时间序列预测模型适用于含有时间变量的模型预测&#xff0c;对中短期的预测有着较好的结果&#xff0c;对长期预测不适用。本文重点介绍ARIMA模型的原理及代码实现。 其他模型总结&#xff1a;​【Python】Python中的经典时间序列预测模型总结_风度78的博客-C…

Transformer 在时间序列预测中的应用

2017年&#xff0c;Google的一篇 Attention Is All You Need 为我们带来了Transformer&#xff0c;其在NLP领域的重大成功展示了它对时序数据的强大建模能力&#xff0c;自然有人想要把Transformer应用到时序数据预测上。在Transformer的基础上构建时序预测能力可以突破以往的诸…

【推荐收藏】11种比较常用的时间序列预测模型

时间序列及其预测是日常工作中建模&#xff0c;分析&#xff0c;预测的重要组成部分。 本文我们将从0开始介绍时间序列的含义&#xff0c;模型及其分析及其常用的预测模型。 文章目录 交流时间序列定义时间序列预测模型与方法原始数据朴素法简单平均法移动平均法指数平滑法一次…

时间序列预测的20个基本概念总结

1、时间序列 时间序列是一组按时间顺序排列的数据点 比如&#xff1a; 每小时的气压每年的医院急诊按分钟计算的股票价格 2、时间序列的组成部分 时间序列数据有三个主要组成部分。 趋势季节性残差或白噪声 3、趋势 在时间序列中记录的长期缓慢变化/方向。 4、季节性 …

时间序列-预测(Forcasting):时间序列预测算法总结

一、背景介绍 绝大部分行业场景,尤其是互联网、量化行业,每天都会产生大量的数据。金融领域股票价格随时间的走势;电商行业每日的销售额;旅游行业随着节假日周期变化的机票酒店价格等; 我们称这种不同时间收到的,描述一个或多种特征随着时间发生变化的数据,为时间序列…

时间序列预测 | ARMA应用指南

ARMA可谓是时间序列最为经典常用的预测方法&#xff0c;广泛应有于涉及时间序列的各个领域。ARMA模型自出道以来&#xff0c;出场次数不可胜数。想必大家也都不陌生&#xff0c;常学常新&#xff0c;我们今天不妨再来回顾一遍&#xff5e;。 ARMA全称Autoregressive moving ave…

时间序列预测的7种方法

import pandas as pd#取数 #dfpd.read_csv(jetrail.csv) #print(df.head()) ID Datetime Count 0 0 25-08-2012 00:00 8 1 1 25-08-2012 01:00 2 2 2 25-08-2012 02:00 6 3 3 25-08-2012 03:00 2 4 4 25-08-2012 04:00 2#pr…

Transformer时间序列预测

介绍&#xff1a; 提示&#xff1a;Transformer-decoder 总体介绍 本文将介绍一个 Transformer-decoder 架构&#xff0c;用于预测Woodsense提供的湿度时间序列数据集。该项目是先前项目的后续项目&#xff0c;该项目涉及在同一数据集上训练一个简单的 LSTM。人们认为 LSTM 在…

时间序列预测的8种常用方法简介

时间序列预测的7种方法 1. 朴素预测法&#xff08;Naive Forecast) 如果数据集在一段时间内都很稳定&#xff0c;我们想预测第二天的价格&#xff0c;可以取前面一天的价格&#xff0c;预测第二天的值。这种假设第一个预测点和上一个观察点相等的预测方法就叫朴素法&#xff…

常见的时间序列预测模型python实战汇总

最完整的时间序列分析和预测&#xff08;含实例及代码&#xff09;&#xff1a;https://mp.weixin.qq.com/s/D7v7tfSGnoAqJNvfqGpTQA 1 时间序列与时间序列分析 在生产和科学研究中&#xff0c;对某一个或者一组变量 x(t)x(t) ARIMA 模型对时间序列的要求是平稳型。因此&#…

时间序列预测模型

时间序列数据一般有以下几种特点&#xff1a;1.趋势(Trend) 2. 季节性(Seasonality)。 趋势描述的是时间序列的整体走势&#xff0c;比如总体上升或者总体下降。下图所示的时间序列是总体上升的&#xff1a; 季节性描述的是数据的周期性波动&#xff0c;比如以年或者周为周期&…

【数据分析】基于时间序列的预测方法

时间序列预测 目录 时间序列预测1.时间序列介绍2.原始数据集3.导入数据4.检测时间序列的平稳性5.如何使时间序列平稳5.1 估计和消除趋势5.1.1 对数转换5.1.2 移动平均 5.2 消除趋势和季节性5.2.1 差异化5.2.2 分解 6.预测时间序列6.1 AR Model6.2 MA Model6.3 Combined Model6.…