并查集(Disjoint Set Union,DSU)
定义:
并查集是一种用来管理元素分组情况的数据结构。
作用:
查询元素a和元素b是否属于同一组
合并元素a和元素b所在的组
优化方法:
1.路径压缩
2.添加高度属性
拓展延伸:
分组并查集
带权并查集
代码如下:
//带有路径压缩的并查集
//一句话并查集(常用)
int dsu(int x){
return x==par[x]?x:(par[x]=dsu(par[x]));
}
//带有路径压缩和高度的并查集
//ranks[i]代表以i为根的树的最大高度,若不存在则为0
int rank[maxn];
int par[maxn];
void init(int n){
for(int i=0;i<n;i++){
par[i]=i;
rank[i]=0;
}
}
int dsu(int x){
if(par[x]==x){
return x;
}else{
return par[x]=dsu(par[x]);
}
}
void union(int x,int y){
int fx=dsu(x);
int fy=dsu(y);
if(fx==fy){
return;
}
if(rank[fx]<rank[fy]){
par[fx]=fy;
}else if(rank[fx]>rank[fy]){
par[fy]=fx;
}else{
par[fy]=fx;
rank[fx]++;
}
}
bool same(int x,int y){
return dsu(x)==dsu(y);
}
poj1182 食物链
//带权并查集解法
/*
模仿矢量计算来处理权值
当我们知道x与祖先x1的关系,y与祖先y1的关系,x与y的关系时,求x1与y1的关系时,使用矢量
计算:
x1->x ->y ->y1
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=50010;
int par[maxn],ran[maxn];
int dsu(int x){
if(x==par[x]){
return x;
}else{
int fx=dsu(par[x]);
//一开始将par[x]写成了fx,一直wa
//如果是fx,那么每一次都到最终的根节点,求解ran数组显然不正确
ran[x]=(ran[x]+ran[par[x]]+3)%3;
par[x]=fx;
return par[x];
}
}
int main()
{
int n,m;
int ty,x,y,ans=0;
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++){
par[i]=i;
ran[i]=0;
}
while(m--){
scanf("%d%d%d",&ty,&x,&y);
if(x==y&&ty==2){
ans++;
}
else if(x>n||y>n){
ans++;
}
else{
int fx=dsu(x);
int fy=dsu(y);
if(fx==fy)
{
if((ran[x]-ran[y]+3)%3!=ty-1){
ans++;
//这里如果不相等,说明这句话是错误的,continue
//一开始因为没写continue,一直wa
continue;
}
}
par[fx]=fy;
ran[fx]=(-ran[x]+ty-1+ran[y]+3)%3;
}
}
printf("%d\n",ans);
return 0;
}
//分组并查集解法
/*
个人理解带权并查集就是多个并查集,
然后一个set所代表的的关系不仅一种,
所以对每个元素要用多重表示,在这个题目里
就是+i*n来区分每个元素和另一些元素的不同关系
*/
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath> using namespace std; const int maxn = 200000+10;
int par[maxn]; int dsu(int x){
return x==par[x]?x:(par[x]=dsu(par[x]));
}
bool same(int x,int y){
return dsu(x)==dsu(y);
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<=3*n;i++){
par[i]=i;
}
int cnt=0;
int x,y,ty;
while(m--){
scanf("%d%d%d",&ty,&x,&y);
if(x<=0||x>n||y<=0||y>n){
cnt++;
continue;
}
if(ty==1){
if(same(x,y+n)||same(y,x+n)){
cnt++;
}else{
for(int i=0;i<3;i++){
int fx=dsu(x+i*n);
int fy=dsu(y+i*n);
par[fx]=fy;
}
}
}else{
if(x==y||same(x,y)||same(y,x+n)){
cnt++;
}else{
for(int i=0;i<3;i++){
int fx=dsu(x+i*n);
int fy=dsu(y+(i+1)%3*n);
par[fx]=fy;
}
}
}
}
printf("%d\n",cnt);
return 0;
}
并查集(Disjoint Set Union,DSU)的更多相关文章
- 【算法导论-36】并查集(Disjoint Set)具体解释
WiKi Disjoint是"不相交"的意思.Disjoint Set高效地支持集合的合并(Union)和集合内元素的查找(Find)两种操作,所以Disjoint Set中文翻译 ...
- 并查集(Disjoint Set)
在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中.这一类问题其特点是看似并不复杂, ...
- 【数据结构】【计算机视觉】并查集(disjoint set)结构介绍
1.简述 在实现多图像无序输入的拼接中,我们先使用surf算法对任意两幅图像进行特征点匹配,每对图像的匹配都有一个置信度confidence参数,来衡量两幅图匹配的可信度,当confidence> ...
- 【算法与数据结构】并查集 Disjoint Set
并查集(Disjoint Set)用来判断已有的数据是否构成环. 在构造图的最小生成树(Minimum Spanning Tree)时,如果采用 Kruskal 算法,每次添加最短路径前,需要先用并查 ...
- 树上统计treecnt(dsu on tree 并查集 正难则反)
题目链接 dalao们怎么都写的线段树合并啊.. dsu跑的好慢. \(Description\) 给定一棵\(n(n\leq 10^5)\)个点的树. 定义\(Tree[L,R]\)表示为了使得\( ...
- HDOJ1232 并查集
所谓并查集 并:Union 查:Find 定义 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.常常在使用中以森林来表示. 集就是让每个元素构成一个单 ...
- Network-POJ3694并查集+LCA
Network Time Limit: 5000MS Memory Limit: 65536K Description A network administrator manages ...
- 并查集(Java实现)
(最好在电脑下浏览本篇博客...手机上看代码不方便) 当时学的时候看的一本印度的数据结构书(好像是..有点忘了..反正跟同学们看的都不一样...)...里面把本文提到的所有情况都提到了,我这里只是重复 ...
- 编程算法 - 食物链 并查集 代码(C)
食物链 并查集 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 有N仅仅动物, 分别编号为1,2,...,N. 全部动物都属于A,B,C中的一种 ...
随机推荐
- webpack 学习2 入口(entry)和输入管理(output)
在开始上代码之前,先让我们盘一盘什么是webpack中的入口和输入 入口 假设你现在手里有一个水龙头,然后十个人用水管从你这里拿水.你这个龙头就是水的入口,水管就是你和这些人的依赖联系.现在供水局的要 ...
- springboot不能用 @SpringApplicationConfiguraction 解决方案
@SpringApplicationConfiguraction 是在springboot 1.4之前,之后改用 @RunWith(SpringJUnit4ClassRunner.class) @S ...
- 【leetcode】835. Image Overlap
题目如下: 解题思路:抛开移动的过程只看移动完成的结果,记图片左上角为顶点,正方形边长为board,要使得两个图片要有重叠,那么一定其中一张图片的顶点和另外一张图片的某一个点重合.假设图片A的顶点A( ...
- Nacos 1.1.4 发布,业界率先支持 Istio MCP 协议
Nacos是阿里巴巴开源的服务发现与配置管理项目,本次发布的1.1.4版本,主要带来的是与Istio的对接功能,使用的是Istio最新的MCP协议.本文将介绍包括这个功能在内的新版本发布的功能. 升级 ...
- Hibernate 单项多对1
自己理解: 单向1对多. 一个客户可以发出多个订单.但是一个订单只属于一个客户. 写对象的时候.在多的那个类对象把1的作为自己的一个属性. 写配置文件 <many-to-one name=1的属 ...
- PHP filter_var_array() 函数
定义和用法 filter_var_array() 函数获取多个变量,并进行过滤. 该函数对过滤多个值很有用,无需重复调用 filter_var(). 如果成功,则以数组形式返回请求变量的值.如果失败, ...
- [CSP-S模拟测试]:F(DP+线段树)
题目传送门(内部题49) 输入格式 第一行四个整数$n,q,a,b$.接下来$n$行每行一个整数$p_i$. 输出格式 一行一个整数表示答案. 样例 样例输入: 10 3 3 7 样例输出: 数据范围 ...
- [CSP-S模拟测试]:简单的区间(分治)
题目描述 给定一个长度为$n$的序列$a$以及常数$k$,序列从$1$开始编号.记$$f(l,t)=\sum \limits_{i=l}^ra_i-\max \limits_{i=l}^r\{a_i\ ...
- System.IO.Path 文件名、路径、扩展名处理
string filePath =@"E:/Randy0528/中文目录/JustTest.rar"; 更改路径字符串的扩展名.System.IO.Path.ChangeExten ...
- python自动化之函数封装
函数最重要的目的是方便我们重复使用相同的一段程序. 将一些操作隶属于一个函数,以后你想实现相同的操作的时候,只用调用函数名就可以,而不需要重复敲所有的语句. 前面一些记录了selenium的各种API ...