并查集

定义:并查集是一种树形的数据结构,用于处理一些不相交集合的合并及查询问题

主要构成:

并查集主要由一个整型数组pre[]和两个函数find()、join()构成。

数组pre[]记录了每个点的前驱结点是谁,函数find(x)用于查找指定结点x属于哪个集合,函数join(x,y)用于合并两个结点x和y。

作用:

并查集的主要作用是求联动分支数。

代表元:

用集合中的某个元素来代表这个集合,则该元素称为此集合的代表元

find()函数的定义与实现:

 int find(int x){
  while(pre[x]!=x) //如果代表元不是自己
  x = pre[x]; //x继续向上找其上级,直到找到代表元为止
  return x;
 }

join()函数的定义与实现:

 void join(int x,int y){
  int fx = find(x),fy=find(y);
  if(fx!=fy)
  pre[fx] = fy;
 }

路径压缩算法:将x到根节点路径上的所有点的上级都设为根节点

 //递归实现
 int find(int x){
  if(pre[x] == x) return x;
  return pre[x] = find(pre[x]);
 }
 //循环实现
 int find(int x) {
  while(x!=pre[x])x=pre[x]=pre[pre[x]];
  return x;
 }

总结:

1、用集合中的某个元素来代表这个集合,则该元素称为此集合的代表元; 2 、一个集合内的所有元素组织成以代表元为根的树形结构; 3 、对于每一个元素 x,pre[x] 存放 x 在树形结构中的父亲节点(如果 x 是根节点,则令pre[x] = x); 4 、对于查找操作,假设需要确定 x 所在的的集合,也就是确定集合的代表元。可以沿着pre[x]不断在树形结构中向上移动,直到到达根节点。 因此,基于这样的特性,并查集的主要用途有以下两点: 1、维护无向图的连通性(判断两个点是否在同一连通块内,或增加一条边后是否会产生环); 2、用在求解最小生成树的Kruskal算法里。

 //代码汇总
 const int N = 1005 //指定并查集所能包含的元素个数
 int pre[N];
 int rank[N];
 void init(int n){
  for(int i=0;i<n;i++){
  pre[i] = i;//每个节点的上一级都是自己
  rank[i] = 1;
  }
 }
 int find(int x){
  if(pre[x] == x) return x;
  return find(pre[x]);
 }
 int find(int x){
  if(pre[x] == x) return x;
  return pre[x] = find(pre[x]);
 }
 //判断两个结点是否连通
 bool isSame(int x,int y){
  return find(x) == find(y);
 }
 ​
 bool join(int x,int y){
  x = find(x);
  y = find(y);
  if(x == y) return false;
  if(rank[x] >rank[y]) pre[y] = x;
  else{
  if(rank[x] == rank[y]) rank[y]++;
  pre[x] = y;
  }
  return true;
 }

例:炼丹术

题目描述

三水最近在学习炼丹术。但是众所周知炼丹术是一门危险的学科,需要大量的调参才能保证安全。好在三水在洗衣机里面找到了一张失传已久的图纸,里面记录了若干种材料的药性。这张图纸上记录了 n种不同的药材,对于每种药材,都需要恰好一种药材来使其稳定 (这种药材可能是其自身,即这种药材本身就很稳定)。三水想知道,通过这张图纸,可以得到多少种不同的稳定的丹方。保证每种药材只会作为稳定剂出现一次。

我们认为一个丹方是从 n种药材中选择若干种 (不为 0 ),两个丹方被认为是不同的当且仅当存在一种药材在其中一个丹方中且不在另一个中。我们称一个丹方是稳定的,当且仅当所有出现在丹方中的药材的稳定剂也在药材中。

因为输出结果可能很大,所以答案对 998244353 取模。

输入描述

第一行一个数字 nn , 表示有 n (1\leqslant n\leqslant 10^6)n(1⩽n⩽106) 种不同的药材。 接下来一行 n个数字,第 i数字 a_i (1\leqslant a_i\leqslant n)a**i(1⩽a**in) 表示药材 ii 的稳定剂是 a_ia**i,保证输入是 11 到 nn 的一个全排列。

输出描述

一个整数 nn ,表示答案对 998244353 取模的结果。

样例输入
  6 2 3 4 5 6 1 
样例输出
  1
思路:
AC代码
 #include<cstdio>
 #include<iostream>
 const int MAXN=1000005;
 const int INF=0x3f3f3f3f;
 const int mod=998244353;
 ​
 using namespace std;
 ​
 int pre[MAXN], a[MAXN];
 ​
 int find(int x) {
  while(x!=pre[x])x=pre[x]=pre[pre[x]];
  return x;
 }
 int pow(int n) {
  int ans=1,base=2;
  for(int i=1;i<=n;++i) {
  ans=(ans*base)%mod;
  }
  return ans;
 }
 int main() {
  int n;
  scanf("%d",&n);
  for(int i=1;i<=n;++i) {
  scanf("%d",&a[i]);
  pre[i]=i;//初始化查数组
  }
  for(int i=1;i<=n;++i) {
  int u=find(i), v=find(a[i]);//通过前缀数组更新并查集,查询过程中进行路径压缩
  if(u!=v)pre[u]=v; //合并相关联集合
  }
  int cnt=0;
  for(int i=1;i<=n;++i) { //记录不同集合个数
  if(pre[i]==i) cnt++;
  }
  printf("%d",pow(cnt)-1);
  return 0;
 }
 

并查集——以nuist OJ P1648炼丹术为例的更多相关文章

  1. Leetcode之并查集专题-765. 情侣牵手(Couples Holding Hands)

    Leetcode之并查集专题-765. 情侣牵手(Couples Holding Hands) N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手. 计算最少交换座位的次数,以便每对情侣可以并 ...

  2. 安科 OJ 1190 连接电脑 (并查集)

    时间限制:1 s 空间限制:128 M 传送门:https://oj.ahstu.cc/JudgeOnline/problem.php?id=1190 题目描述 机房里有若干台电脑,其中有一些电脑已经 ...

  3. 并查集练习(0743) SWUST OJ

    #include<iostream> #include<cstring> using namespace std; ]; int n,m,l,ci,di; int root(i ...

  4. 杭电OJ——1198 Farm Irrigation (并查集)

    畅通工程 Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅通工程"的目标是使全省任何两个城镇间都可 ...

  5. 洛谷OJ P1196 银河英雄传说(带权并查集)

    题目描述 公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦 创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银河系的两大军事集团在巴米利恩星域爆发战争.泰山 ...

  6. 九度OJ 1446 Head of a Gang -- 并查集

    题目地址:http://ac.jobdu.com/problem.php?pid=1446 题目描述: One way that the police finds the head of a gang ...

  7. 九度OJ 朋友圈 -- 并查集

    题目地址:http://ac.jobdu.com/problem.php?pid=1526 题目描述: 假如已知有n个人和m对好友关系(存于数字r).如果两个人是直接或间接的好友(好友的好友的好友.. ...

  8. [Swust OJ 772]--Friend(并查集+map的运用)

    题目链接:http://acm.swust.edu.cn/problem/772/ Time limit(ms): 1000 Memory limit(kb): 65535    Descriptio ...

  9. [Swust OJ 1091]--土豪我们做朋友吧(并查集,最值维护)

    题目链接:http://acm.swust.edu.cn/problem/1091/ Time limit(ms): 1000 Memory limit(kb): 32768   人都有缺钱的时候,缺 ...

随机推荐

  1. ACM - 动态规划 - UVA437 The Tower of Babylon

    UVA437 The Tower of Babylon 题解 初始时给了 \(n\) 种长方体方块,每种有无限个,对于每一个方块,我们可以选择一面作为底.然后用这些方块尽可能高地堆叠成一个塔,要求只有 ...

  2. 顺利通过EMC实验(1)

  3. 微信小程序要求HTTPS,如何选择SSL证书?

    为了保护小程序应用安全,微信官方的需求文档要求,每个微信小程序必须事先设置一个通讯域名,并通过HTTPS请求进行网络通信,不满足条件的域名和协议无法请求.因此开发者应先准备好配置好HTTPS证书的域名 ...

  4. 如何利用WebSocket实现网页版聊天室

    花了将近一周的时间终于完成了利用WebSocket完成网页版聊天室这个小demo,期间还走过了一段"看似弯曲"的道路,但是我想其实也不算是弯路吧,因为你走过的路必将留下你的足迹.这 ...

  5. python-爬楼梯

    [题目描述] 假设一段楼梯共n(n>1)个台阶,小朋友一步最多能上3个台阶,那么小朋友上这段楼梯一共有多少种方法. [练习要求]请给出源代码程序和运行测试结果,源代码程序要求添加必要的注释. [ ...

  6. (ICONIP2021)On the Unreasonable Effectiveness of Centroids in Image

    目录 摘要 1.引言 2.提出的方法 2.1 CentroidTripletloss 2.2 聚合表示 3.实验 3.1 数据集 3.2 应用细节 3.3 Fashion检索结果 3.4 行人再识别结 ...

  7. Z-blog csrf漏洞学习

    Z-blog csrf 环境搭建 1. 首先我在本地搭了一个z-blog. ​ 思路:csrf并不侧重于哪种功能点,只要检测不规范,就可能利用成功,所以我考虑了一下后台添加管理员的地方. 数据包构造 ...

  8. Django + Taro 前后端分离项目实现企业微信登录

    前言 还是最近在做的一个小项目,后端用的是Django搭配RestFramework做接口,前端第一次尝试用京东开源的Taro框架来做多端(目前需要做用于企业微信的H5端和微信小程序) 本文记录一下企 ...

  9. 在Vue3项目中使用pinia代替Vuex进行数据存储

    pinia是一个vue的状态存储库,你可以使用它来存储.共享一些跨组件或者页面的数据,使用起来和vuex非常类似.pina相对Vuex来说,更好的ts支持和代码自动补全功能.本篇随笔介绍pinia的基 ...

  10. CesiumJS 2022^ 原理[2] 渲染架构之三维物体 - 创建并执行指令

    目录 回顾 预备知识:指令 预备知识:通道 1. 生成并执行指令 1.1. Primitive 生成指令 1.2. Context 对象负责执行 WebGL 底层代码 2. 多段视锥体技术 3. 指令 ...