并查集——以nuist OJ P1648炼丹术为例
并查集
定义:并查集是一种树形的数据结构,用于处理一些不相交集合的合并及查询问题
主要构成:
并查集主要由一个整型数组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**i⩽n) 表示药材 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炼丹术为例的更多相关文章
- Leetcode之并查集专题-765. 情侣牵手(Couples Holding Hands)
Leetcode之并查集专题-765. 情侣牵手(Couples Holding Hands) N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手. 计算最少交换座位的次数,以便每对情侣可以并 ...
- 安科 OJ 1190 连接电脑 (并查集)
时间限制:1 s 空间限制:128 M 传送门:https://oj.ahstu.cc/JudgeOnline/problem.php?id=1190 题目描述 机房里有若干台电脑,其中有一些电脑已经 ...
- 并查集练习(0743) SWUST OJ
#include<iostream> #include<cstring> using namespace std; ]; int n,m,l,ci,di; int root(i ...
- 杭电OJ——1198 Farm Irrigation (并查集)
畅通工程 Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅通工程"的目标是使全省任何两个城镇间都可 ...
- 洛谷OJ P1196 银河英雄传说(带权并查集)
题目描述 公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦 创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银河系的两大军事集团在巴米利恩星域爆发战争.泰山 ...
- 九度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 ...
- 九度OJ 朋友圈 -- 并查集
题目地址:http://ac.jobdu.com/problem.php?pid=1526 题目描述: 假如已知有n个人和m对好友关系(存于数字r).如果两个人是直接或间接的好友(好友的好友的好友.. ...
- [Swust OJ 772]--Friend(并查集+map的运用)
题目链接:http://acm.swust.edu.cn/problem/772/ Time limit(ms): 1000 Memory limit(kb): 65535 Descriptio ...
- [Swust OJ 1091]--土豪我们做朋友吧(并查集,最值维护)
题目链接:http://acm.swust.edu.cn/problem/1091/ Time limit(ms): 1000 Memory limit(kb): 32768 人都有缺钱的时候,缺 ...
随机推荐
- SpringMVC的入门程序
1.环境准备(jar包) 2.在web.xml中配置前端控制器 <!-- springmvc 前端控制器 --> <servlet> <servlet-name>s ...
- MyBatis Plus 2.3 个人笔记-03-Active Record
AR 语法糖 是一种领域模型模式,特点就是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一条记录 实现AR [在代码生成器中可以添加配置] import com.baomidou ...
- java后台解决上传图片翻转90的问题,有demo,经过测试可用
1.需要加入 依赖 metadata-extractor.jar 依赖如下 <dependencies> <!-- Extracts Exif, IPTC, XMP, ICC and ...
- 4-Pandas数据预处理之数据转换(df.map()、df.replace())
在数据分析中,根据需求,有时候需要将一些数据进行转换,而在Pandas中,实现数据转换的常用方法有: 利用函数或是映射 可以将自己定义的或者是其他包提供的函数用在Pandas对象上实现批量修改. ap ...
- 开关电源PCB排版,基本要点分析
1 开关电源PCB排版基本要点 1.1 电容高频滤波特性 图1是电容器基本结构和高频等效模型. 电容的基本公式是 式(1)显示,减小电容器极板之间的距离(d)和增加极板的截面积(A)将增加电容器的电容 ...
- python-转换函数使用
输入一个整数和进制,转换成十进制输出 输入格式: 在一行输入整数和进制 输出格式: 在一行十进制输出结果 输入样例: 在这里给出一组输入.例如: 45,8 输出样例: 在这里给出相应的输出.例如: 3 ...
- AS之AlertDialog使用
关于AlertDialog的使用,主要是去做一个弹窗. import android.content.DialogInterface; import android.os.Bundle; import ...
- java中什么叫多重捕获MultiCatch,它的用法是怎样的?
2.多重捕获MultiCatch 马克-to-win:什么叫多重捕获MultiCatch?一段代码可能引起多个异常,这时可以定义两个或更多的catch子句来处理这种情况,每个子句捕获一种类型的异常.马 ...
- vuejs兄弟组件之间的通信
var Event = new Vue();//准备一个空的实例对象 //A组件 var A = { template: ` <div> <span>我是A组件的数据-> ...
- EbitenCookBook中文教程 第一课:安装 Ebiten
本文实时更新原址:https://ebitencookbook.vercel.app/docs/CookBook_Start/class1 第一课 安装 Ebiten 欢迎大家来到 Ebiten 中文 ...