并查集(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中的一种 ...
随机推荐
- python数字图像处理(一)图像的常见操作
首先导入必要的库,使用Opencv读入图像,避免复杂的图像解析,同时使用Opencv作为算法的对比,由于使用环境为jupyter使用matplotlib直接可视化 import cv2 import ...
- webpack学习(一)起步安装
起步 webpack 用于编译 JavaScript 模块.一旦完成安装,你就可以通过 webpack 的 CLI 或 API 与其配合交互.如果你还不熟悉 webpack,请阅读核心概念和打包器 ...
- openwrt 编译支持sqlite3
编译版本加载lib库 ------------------------------Libraries----------------------------------- Filesystem -- ...
- hdu 6103 Kirinriki (枚举对称中心+双指针)
Problem Description We define the distance of two strings A and B with same length n isdisA,B=∑(i=0 ...
- iframe中涉及父子页面跨域问题
什么是跨域? 跨域,指的是浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器施加的安全限制.所谓同源是指相同的域名.协议和端口,只要其中一项不同就为跨域. 举几个例子: http:/ ...
- Python之-异常处理
1.python中处理异常的方式 #coding:utf8 filename=raw_input("请输入你要操作的文件") try: f=open(filename) print ...
- 前端每日实战:57# 视频演示如何用纯 CSS 创作一双黑暗中的眼睛
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/xzYVzO 可交互视频 此视频是可 ...
- nodejs操作消息队列RabbitMQ
一. 什么是消息队列 消息队列(Message Queue,简称MQ),从字面意思上看,本质是个队列,FIFO先入先出,只不过队列中存放的内容是message而已.其主要用途:不同进程Process/ ...
- win10配置 samba
一.先確認Linux中smb正確配置可以使用命令smbclient -L //localhost/ 二.win10配置1.打開win10對smb1.0/cifs檔共用支援2.本地群組原則編輯,修改如下 ...
- SSO 实现博客系统的单点登录
https://blog.csdn.net/qq1350048638/article/details/78933375 https://blog.csdn.net/yejingtao703/artic ...