并查集(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中的一种 ...
随机推荐
- 【Flutter学习】之DateTime日期转换
概述: 表示一个时间点 通过构造函数或解析格式化的字符串创建DateTime对象,并且符合ISO 8601标准的子集,小时是24小时制,范围在0-23之间 DateTime对象创建之后,将是固定不变的 ...
- postgresql中rank() over, dense_rank(), row_number() 的用法和区别
- Delphi UTF编码 UTF8Encode、UTF8Decode、URLEncode、URLDecode
一.URL简介 URL是网页的地址,比如 http://www.cnblogs.com.Web 浏览器通过 URL 从 web 服务器请求页面. 由于URL字符串常常会包含非ASCII字符 ...
- hdu1166 敌兵布阵 (线段树单点更新)
Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营 地,Derek和Tidy的任务就是要监视这 ...
- sql server 基础语法2
别名,选择,查询,排序,去重,筛选 select * from UserInfo as ui --起别名 select UserName,UserPwd --指定选择的列 from UserInfo ...
- Python基础教程(011)--程序开发中的错误及原因
前言 排查代码开发中的错误 内容 1,编写的程序不能正常执行,或者执行的结果不是我们期望的 2,俗称bug,是程序开发常见的,初学常见的原因有 手误 对已经学习的知识点理解不足 对语音还有需要学习和提 ...
- Panel
在Panel上绘图的实现 近期制作了FDS的一个建模工具,由于知识有限,做出的效果是2D的.昨天上课的时候看老师画一个长方体,突然想到,为什么不给普通的2D图形加画上几条直线,就能实现2D图形的3D视 ...
- Selenium之Android使用学习
20140507 Selenium一般用在web自动化上,为什么Android上也能用呢? 如图,手机端和DB联动:手机端的客户端给server发数据流,进行增删改查操作,这种写数据用update更新 ...
- 经典的MySQL Duplicate entry报错注入
SQL注射取数据的方式有多种: 利用union select查询直接在页面上返回数据,这种最为常见,一个前提是攻击者能够构造闭合的查询. Oracle中利用监听UTL_HTTP.request发起的H ...
- error LNK2005: __get_invalid_parameter_handler 已经在 LIBCMTD.lib(invarg.obj) 中定义
转自VC错误http://www.vcerror.com/?p=166 问题描述: 在用vs2012编译程序的时候,release版本正常编译通过,但Debug版本提示下面的很多错误; 1>LI ...