首页 > 其他分享 >并查集

并查集

时间:2023-10-15 12:33:27浏览次数:36  
标签:return int 查集 fa 自环 find

并查集

如果有一个关系网,我们需要建立两点之间的关系,如果仅用一维链表 ,则有可能无法考虑到两点同为一点 “儿子”的 情况,则 我们需要建立一个方式,从而直接对比两点“祖父”。

一 .递归查询

int find(int x){
  if(fa[x]==x)return x;//只有祖父自环,如果他也自环,则找到父节点
  return find(fa[x]);//不然往父节点继续靠近
}

二.合并两节点

void add(int xx,int yy){
  int fa_xx=find(xx);
  int fa_yy=find(yy);
  fa[fa_xx]=fa_yy;//将两者合并
}

以上为基础并查集,记得要初始化:在每一个数在建立关系前与自己自环.

现在我们可以开始想想大样例该如何过了。

加如题目告诉你 1-7,7-3,3-4,5-6,2-6,1-2,然后询问你5,4是否有关系,按原本方法可得画图:

 

 根据树形图可知;两者都是1的子孙,但是查询次数多,如果更大的数据可能会爆,所以我们可以考虑在每一次更新后将点值更新为祖先值。

 如此反复跟新,便可以将速度大为优化,代码中优化也很简单 

int find(int x){
  if(fa[x]==x)return x;//只有祖父自环,如果他也自环,则找到父节点

  fa[x]=find(fa[x]);//每次更新点值
  return fa[x];//不然往父节点继续靠近
}

如此这般 便完成优化了。

三.例题试炼

1.P1551 亲戚 

简单模板,直接调用即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,p,t[100000]; int a,b;
 4 int find(int x){
 5     if(t[x]==x)return x;
 6     return t[x]=find(t[x]);
 7 }
 8 void add(int x,int y){
 9     int fa_x=find(x);
10     int fa_y=find(y);
11     t[fa_x]=fa_y;
12 }
13 int main(){
14     
15     cin>>n>>m>>p;
16     for(int i=1;i<=n;i++)t[i]=i;
17     for(int i=1;i<=m;i++){
18         cin>>a>>b;
19         add(a,b);
20     }
21     for(int i=1;i<=p;i++){
22         cin>>a>>b;
23         if(find(a)==find(b))cout<<"Yes"<<endl;
24         else cout<<"No"<<endl;
25     }
26     
27     return 0;
28 }

2.P3367 【模板】并查集

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,z,x,y;
 4 int a[10010];
 5 int find(int q){
 6     if(a[q]==q)return q;
 7     return a[q]=find(a[q]);
 8 }
 9 int main(){    
10     cin>>n>>m;
11     for(int i=1;i<=n;i++)a[i]=i;
12     for(int i=1;i<=m;i++){
13         cin>>z>>x>>y;
14         if(z==1){
15             a[find(x)]=find(y);
16             
17         }else{
18             if(find(x)==find(y))cout<<"Y"<<endl;
19             else cout<<"N"<<endl;
20         }
21     }
22      
23 
24 return 0;
25 }

 

标签:return,int,查集,fa,自环,find
From: https://www.cnblogs.com/happy-yu/p/17765510.html

相关文章

  • 并查集的实现【学习算法】
    并查集的实现【学习算法】前言版权推荐并查集的实现最后前言2023-9-2614:38:02以下内容源自《【学习算法】》仅供学习交流使用版权禁止其他平台发布时删除以下此话本文首次发布于CSDN平台作者是CSDN@日星月云博客主页是禁止其他平台发布时删除以上此话推荐算法讲解056【必备】并......
  • 并查集
    基本的并查集OI-wikiLink并查集,一种用于管理元素所属集合的数据结构,形如一片森林,同一棵树内的元素所属同一集合,不同树内的元素不属于同一集合。将并查集拆分一下。并,合并;查,查询;集,处理的是集合相关内容。所以并查集一共有两种操作:合并两元素对应集合、查询某元素所属集合(查......
  • 数据结构-并查集
    并查集的使用范围:1.合并集合2.查询两元素是否属于同一集合   高级用法:  3.进行集合划分<带权并查集>  4.连通块块数查询&块内元素个数统计<连通图>  5.撤销合并<可持久化并查集>//本文暂不涉及,我还不会并查集基本操作:#definerep(i,n)for(int......
  • 线段树分治&可撤销并查集
    可撤销并查集按时间顺序用一个栈维护合并信息,撤销时从栈顶弹出合并信息,恢复原状态。并查集查找祖先时不能路径压缩,只能按秩合并。例题:[ABC302Ex]BallCollector容易想到将\(A_i\)和\(B_i\)之间连边。遍历整棵树,用可撤销并查集维护图。为了进一步求得答案,需要注意到该......
  • 可持久化非确定状态AC自动分块维护线段平衡仙人掌优化最小费用最大流预处理混合图上莫
    P8946TheLostSymbol这种类型的dp的特点就是大部分转移形如\(f(i,j)\rightarrowf(i+1,j+1)\)之类的,并且当以上转移出现时原数组被清空,这就可以用一个deque来维护,然后对于全局赋值/全局加,需要对每个位置维护一个时间戳,并记录上一次赋值/加是什么时候,以便标记下传。(貌似......
  • 倍增并查集
    假如说我们有\(n\)个元素,\(m\)次操作。每次操作给定\(x,y,z\),要求对于任意\(0\lei\lez\),将\(x+i\)和\(y+i\)合并,求最后的并查集形态。数据范围是\(10^5\)级别的。我们考虑将\(z\)二进制拆分,那么可以将\(z\)分解为\(O(\logn)\)个\(2\)的整数次幂之和,也就可......
  • poj 1182 食物链---带权值的并查集
    这题就一组数据,用while(scnaf(“%d%d”,&n,&m)!=EOF)..就wa了,我wa了数次,无语了。。带权值的并查集,d[]数组存的是每个点和根节点的关系,同类为d[i]=0; 根节点吃i点为d[i]=1; i点吃根节点为d[i]=2;自己画图感受一下吧!!#include<stdio.h>#include<string.h>#include<stdlib.h>in......
  • hdu-3926-Hand in Hand-并查集
    判断两个图是否同构。。用了并查集。。#include<stdio.h>#include<string.h>#include<stdlib.h>#include<algorithm>#include<queue>#include<stack>usingnamespacestd;#definelllonglongintn,m;structnode{ intfu; intsum; intf......
  • 并查集 堆排序 (9/10)
    并查集模板 注意查找到后查找的节点直接连接根节点#include<iostream>usingnamespacestd;constintN=100010;intp[N];//关键记住find函数intfind(inta){if(p[a]!=a)p[a]=find(p[a]);//不等于根节点就往头结点走,并且等于returnp[a];}intma......
  • (测试)带权并查集
    带权并查集普通的并查集只能维护每个节点所在集合的编号,带权并查集则可以维护集合内任意一点到所在集合根的距离。带权并查集是结点存有权值信息的并查集。相比于一般的并查集,带权并查集需要开辟两个数组:一个是dsu[N],用来判断集合关系;一个是dis[N],用来描述其与根节点的关系。当......