并查集——以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 人都有缺钱的时候,缺 ...
随机推荐
- 学习k8s(二)
kubernetes-国内拉取gcr.io\quay.io镜像方法 方法1: https://hub.docker.com/r/ibmcom/ 例如: gcr.io/google_containers ...
- css技术之用最高和最宽的限制“max-height和max-width”做图片同比例缩放,达到图片不变形目的,做出批量打印图片功能,页面打印“window.print()”
一.简介 他们是为流而生的,像width/height这种定死的砖头式布局,min-width/max-width就没有存在的意义 ,min-width/max-width一定是自适应布局或流体布局中 ...
- 遇到的问题之"项目启动加载不出页面"
已找到解决方案1 需要启动这两个微服务(注意:这个属于个人,你们也可以看看是否关联到相关微服务未启动)
- Idea学习之"使用SVN如何查看哪一行是哪一个人写的历史日志"
点击出的方法 结果图 点击记录,显示详细
- java中Super指向他紧邻的父类,而不是最底层的基类
3.2 当有两次继承时,演示super指向他紧邻的父类 我们把上面的例子扩展成两次继承, 就看出:马克-to-win,Super是一个参考(或说指针)指向他紧邻的父类,而不是最底层的基类. 例1.3. ...
- Android限制输入框内容
<EditText android:id="@+id/temper" android:hint="36.2" android:digits="1 ...
- 进入React的世界
一. React 是什么 1. 声明式写法 2. 组件化 3. 一次学习, 随处编写 二. 为什么要学习React 1. 大厂加持 - Facebook 2. 最流行, 使用人数最多, 最被开发者喜爱 ...
- vue后台管理系统组件弹窗
//addFormVisibleIcon可在data中设置true与falsehttps://element.eleme.io/#/zh-CN/component/installation <e ...
- openlayers离线瓦片地图开发
近期业务繁忙...待更新
- px,rem,em 通过媒体查询统一的代码
@media only screen and (max-width: 1080px), only screen and (max-device-width:1080px) { html,body { ...