并查集

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

主要构成:

并查集主要由一个整型数组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. 深入 x64

      本篇原文为 X64 Deep Dive,如果有良好的英文基础的能力,可以点击该链接进行阅读.本文为我个人:寂静的羽夏(wingsummer) 中文翻译,非机翻,著作权归原作者所有.   由于原文十 ...

  2. ctfhub web 前置技能(请求方式、302跳转、Cookie)

    第一题:请求方式 打开环境分析题目发现当前请求方式为GET 查看源码发现需要将请求方式改为CTFHUB就可以 使用bp抓包 发送到repeater模块修改请求方式 即可得到flag 第二题:302跳转 ...

  3. 6. Git管理远程仓库

    6. Git管理远程仓库 使用远程仓库的目的 作用:备份,实现代码共享集中化管理 Git克隆操作 目的 将远程仓库(github对应的项目)复制到本地 代码 git clone 仓库地址 多学一招:仓 ...

  4. 【STM32】MDK中寄存器地址名称映射分析

    对于MCU,一切底层配置,最终都是在配置寄存器 51单片机访问地址 51单片机经常会引用一个reg51.h的头文件.下面看看它是怎么把名字和寄存器联系在一起的: 1 sfr p0=0x80; 2 p0 ...

  5. 002.MEMS应用在开关电源上,实现大功率超小型化

    设计任务书 1.有关MEMS还有待具体了解 2.有关开关电源的目前难题也需要了解

  6. ES6-11学习笔记--Generator

    基本使用 function后面加个*号 function* foo() { for (let i = 0; i < 3; i++) { yield i; // yield不能作为构造函数去使用, ...

  7. Leetcode1/242/383-HashMap常用方法以及遍历排序方式

    HashMap常用方法以及遍历排序方式 常用方法 map.containsKey() map.put() map1.equals(map2) 遍历方式 Iterator<Map.Entry< ...

  8. uView的DatetimePicker详解

    uView UI号称: 是全面兼容nvue的uni-app生态框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水 亲身感受,用起来真的坑太多, 官方文档太简洁, 很多配置都没说明也没代码, 上百度查 ...

  9. CSS简单样式练习(六)

    运行效果: 源代码: 1 <!DOCTYPE html> 2 <html lang="zh"> 3 <head> 4 <meta char ...

  10. vue中执行npm run build报错解决方法?

    遇到了执行npm run build 后报错: [build:js ] Module not found: Error: Can't resolve 'scss-loader' in 'D:\work ...