首页 > 其他分享 >并查集

并查集

时间:2023-07-28 21:13:43浏览次数:46  
标签:le int 查集 节点 fa xx find

简述

并查集其实是一个很有用的算法(至少我是这么认为的),很简单,代码也很好写,今天突然想写一下并查集。

直接讲并查集不太好说,我们先看下面这一道题:
洛谷 P3367 【模板】并查集

【模板】并查集

题目描述

如题,现在有一个并查集,你需要完成合并和查询操作。

输入格式

第一行包含两个整数 \(N,M\) ,表示共有 \(N\) 个元素和 \(M\) 个操作。

接下来 \(M\) 行,每行包含三个整数 \(Z_i,X_i,Y_i\) 。

当 \(Z_i=1\) 时,将 \(X_i\) 与 \(Y_i\) 所在的集合合并。

当 \(Z_i=2\) 时,输出 \(X_i\) 与 \(Y_i\) 是否在同一集合内,是的输出
Y ;否则输出 N

输出格式

对于每一个 \(Z_i=2\) 的操作,都有一行输出,每行包含一个大写字母,为 Y 或者 N

样例 #1

样例输入 #1

4 7
2 1 2
1 1 2
2 1 2
1 3 4
2 1 4
1 2 3
2 1 4

样例输出 #1

N
Y
N
Y

提示

对于 \(30\%\) 的数据,\(N \le 10\),\(M \le 20\)。

对于 \(70\%\) 的数据,\(N \le 100\),\(M \le 10^3\)。

对于 \(100\%\) 的数据,\(1\le N \le 10^4\),\(1\le M \le 2\times 10^5\),\(1 \le X_i, Y_i \le N\),\(Z_i \in \{ 1, 2 \}\)。

转化

合并两个集合有什么性质呢?我们可以把每一个集合看成一棵树中的节点,把两个集合合并其实就是把两棵树合成一棵。而两个集合在同一棵树中就代表了在一个大集合中。

find函数

可我怎么知道两个集合在不在同一棵树中呢?仔细思考一下,我们需要找到一棵树中所有点的共同特征,同时这个特征要便于维护。建议新手先看着下面的树自己思考。
(这个树上节点的信息是集合,没有采用树上左右儿子的编号方法)

image

根节点一样!是不是恍然大悟?求一个节点所在的树的根节点很简单,一直跳它的父亲就行了(所有节点一开始的父亲是自己,所以跳到节点为自身的节点就找到根节点了)。

对于求一个节点所在树的根节点,我们使用以下代码:

不要贺代码哟
int find(int xx){//没有优化的find函数
	if(xx==fa[xx]) return xx;//fa[xx]为xx的父亲
	else return find(fa[xx]);
}

状态压缩:

为什么代码里写的是“没有优化的find函数”,因为你考虑树其实还好,但如果退化成了一条链,每一次询问都要从最底下找到最上面,时间就爆炸了。

怎么优化呢?你考虑这样一件事,就是你只关心根节点,并不关心中途的祖先,那对于一次find的调用,我们可以把中途的所有点都直接连向根节点,这样下次就可以直接一次到根节点了。

状态压缩后的上图:
image

ps:状态压缩不能维持所有父子关系,对于要求记录父子关系的题目不适用

优化后的find函数

点击查看代码
int find(int xx){
	if(fa[xx]==xx) return xx;
	else return fa[xx]=find(fa[xx]);
}

\(z_i=2\)的代码

对于这道题,\(z_i=2\)就可以愉快地解决了:

点击查看代码
if(z==2){
	int x,y;
	cin>>x>>y;
	if(find(x)==find(y)) cout<<"Y"<<endl;
	else cout<<"N"<<endl;
}

合并(\(z_i=1\))

考虑两棵树的合并,不难理解,我们肯定是把一棵树的根节点\((find(x))\)接到另一棵树的根节点上\((find(y))\)。

点击查看代码
void unionn(int x,int y){
	x=find(x);//x所在树的根节点
	y=find(y);//y所在树的根节点
	fa[x]=y;
}
这样代码的所有部分凑齐了。

全代码:

不要抄袭
#include<bits/stdc++.h>
using namespace std;
int n,m;
int z,x,y;
int fa[10001];

int find(int x){
	if(fa[x]==x) return x;
	else return fa[x]=find(fa[x]);
}

void unionn(int x,int y){
	x=find(x);
	y=find(y);
	fa[x]=y;
}

int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		fa[i]=i;
	}
	for(int i=1;i<=m;i++){
		cin>>z>>x>>y;
		if(z==1){
			unionn(x,y);
		}
		else{
			if(find(x)==find(y)){
				cout<<"Y"<<endl;
			}
			else{
				cout<<"N"<<endl;
			}
		} 
	}
	return 0;
}

标签:le,int,查集,节点,fa,xx,find
From: https://www.cnblogs.com/wangwenhan/p/17588889.html

相关文章

  • 超市-并查集应用
    【超市】【问题描述】超市里有N件商品,每个商品都有利润pi和过期时间di,每天只能卖一件商品,过期商品(即当天di<=0)不能再卖。求合理安排每天卖的商品的情况下,可以得到的最大收益是多少。【输入格式】输入包含多组测试用例,测试用例最多30组。每组测试用例,以输入整数N开始,接下里输......
  • 并查集-讲课内容补全(未完
    施工中......先在这里给出我的并查集模板以下为比较常用的路径压缩intf[MAXN],n,m;voidclean(){for(inti=1;i<=n;i++)f[i]=i;}intfind(intx){if(x!=f[x])f[x]=find(f[x]);returnf[x];}voidadd(intx,inty){intfx=find(x),fy=find(y......
  • The Third Letter带权并查集
    Problem-1850H-Codeforces题意是给你a,b,c说明a在b后面c个单位(c<0就是在左边),每个位置只能有一个数,一共有n个位置,告诉你m个关系,问是否符合条件我们可以设置d[x]表示x到它的最早的父节点的距离,然后如果两个数父节点一样,那么c!=d[a]-d[b]时就说明不符合条件那么对于并查......
  • 算法刷题笔记--并查集的运用
    1、题目描述:一个城市中有两个犯罪团伙A和B,你需要帮助警察判断任意两起案件是否是同一个犯罪团伙所为,警察所获得的信息是有限的。假设现在有N起案件(N<=100000),编号为1到N,每起案件由团伙A或团伙B所为。你将按时间顺序获得M条信息(M<=100000),这些信息分为两类:D[a][b]其中[a]和[b]表示两......
  • 算法学习--并查集相关知识及例题
    一、并查集的定义二、基本操作1、初始化一开始,每个元素都是独立的集合#include<iostream>usingnamespacestd;constintmaxN=1000;intfather[maxN];intmain(){for(inti=1;i<=maxN;i++){father[i]=i;}return0;}2、查找递推版本://返......
  • 【学习笔记】并查集
    先来看百度百科上的定义:并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。并查集是一种树型的数据结构,用于处理一些不相交集合(disjointsets)的合......
  • 并查集
    在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。这一类问题近几年来反复出现在信息学的国际国内竞赛题中,其特点是看似并不复杂,但数据量极大,若用正常的数据......
  • 擒贼先擒王(并查集)
    擒贼先擒王(并查集)目录擒贼先擒王(并查集)题面题目概括思路AC代码和注释题面快过年了,犯罪分子也开始为年终奖奋斗了。晓哼的家乡出现了多次抢劫事件。由于强盗人数过于庞大,作案频繁,警方想查清楚到底有几个犯罪团伙实在太不容易了,不过警察叔叔还是搜集到了一些线索,需要咱们帮忙分析......
  • 并查集知识梳理
    并查集目录并查集并查集的定义并查集的思想朴素并查集的代码(1)初始化(2)查找(3)合并路径压缩(1)查找代码(2)路径压缩完整代码按秩合并思想实现(1)初始化(2)合并并查集的定义并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题。并查集通常包含两种操作:查找(Find):查询两个......
  • 并查集知识点梳理
    并查集目录并查集并查集的定义并查集的思想朴素并查集的代码(1)初始化(2)查找(3)合并路径压缩(1)查找代码(2)路径压缩完整代码按秩合并思想实现(1)初始化(2)合并并查集的定义并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题。并查集通常包含两种操作:查找(Find):查询两个......