并查集(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中的一种 ...
随机推荐
- 第4篇创建harbor私有镜像库
一.部署准备: 1.准备harbor软件包 在部署节点上: 2.挂载一个磁盘,专门存储harbor镜像和文件 3.进入到/etc/docker/harbor/目 ...
- qq for linux tar.gz安装
借用官网的一段话 QQ for Linux 怎么命令行安装和卸载 RPM版本 安装 ①打开控制台,使用管理员身份登录 :②在终端中输入命令“rpm –U package_name.rpm“ , pac ...
- getcwd函数学习
getcwd 函数原型:char *getcwd( char *buffer, int maxlen ); 功 能:获取当前工作目录 参数说明:getcwd()会将当前工作目录的绝对路径复制到参数bu ...
- 科学把妹法 ( ̄▽ ̄)"
曾经有一位生物学人士,公布了工科把妹第一弹,暨“巴甫洛夫把妹法”: 每天给你那位心仪的女同事/女同学的抽屉里都放上精心准备的早餐,并且保持缄默不语,无论她如何询问,都不要说话. 如此坚持一至两个月, ...
- 【MySQL】mysql查询强制大小写及替换字段
强制大小写 select * from test where name like BINARY '%Adc%' mysql替换字段 update test set name= REPLACE (nam ...
- BZOJ 3207: 花神的嘲讽计划Ⅰ(莫队+哈希)
传送门 解题思路 刚开始写了个莫队+哈希+\(map\)的\(O(n\sqrt(n)log(n)\)的辣鸡做法,\(T\)飞了.后来看了看别人博客发现其实并不用拿\(map\)当桶存那些哈希值.因为只 ...
- svm 之 线性可分支持向量机
定义:给定线性可分训练数据集,通过间隔最大化或等价的求解凸二次规划问题学习获得分离超平面和分类决策函数,称为线性可分支持向量机. 目录: • 函数间隔 • 几何间隔 • 间隔最大化 • 对偶算法 1. ...
- 64、saleforce 删除操作举例
String deletePrivelegeRoleSql = 'SELECT ROLEID__c, NAME__c, Id, PRIVELEGEID__r.ID, ROLEID__r.ID FROM ...
- 用 Flask 来写个轻博客 (16) — MV(C)_Flask Blueprint 蓝图
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 Blueprint 蓝图 定义一个蓝图 注册一个蓝图 创建蓝 ...
- sublime useful packages
Package control Prefixr Emmet