poj1988

本文详细介绍了一种数据结构——并查集的实现方法及其在解决特定类型问题上的应用。文章首先介绍了并查集的基本概念,包括其核心操作:查找根节点和合并集合。随后,通过一个具体的例子,展示了如何使用并查集来处理石子堆的操作问题,包括移动石子堆和查询石子数量。此外,还分享了代码实现细节,如路径压缩和集合合并时的元素个数更新策略。

题目链接click here!
题目意思:有n个带序号的石子实现下面两种操作:
1.M 含x的一堆石子整体移动到包含y石子的一堆上面
2.C 输出序号为x的石子下面有多少个石子

模板题稍微改动一下有一篇讲解click here!
1.创建结构体,保存父亲(路径压缩的时候会直接指向根节点)和到根节点的距离(所以不能用一位数组实现)
2.将两个集合合并的时候将含x堆的根节点的距离值更新为含y堆的根节点的父亲取负(代表此集合元素个数取负),父亲更新为y

Here comes the code.

#include<cstdio>
using namespace std;
struct node{
	int fa,d;
}dsu[30005];
node Find(int x){
	node no;
	if(dsu[x].fa<0){
		no.fa=x;
		no.d=0;
		return no;
	}//若直接返回 return node{x,0};会出现编译错误,所以还是谨慎起见 
		no=Find(dsu[x].fa);
		no.d+=dsu[x].d;
		dsu[x]=no;
		return no;
}
void Union(int x,int y){
	x=Find(x).fa;
	y=Find(y).fa;
	if(x==y) return;
	dsu[x].d=-dsu[y].fa;
	dsu[y].fa+=dsu[x].fa;
	dsu[x].fa=y;
}
int p;//也可以定义在main函数里
int main(){
	int x,y;
	char a;
	for(int i=1;i<30004;i++){
		dsu[i].fa=-1;//起初都是-1 
		dsu[i].d=0;
	}
	scanf("%d",&p);
	for(int i=1;i<=p;i++){
		scanf("%s",&a);
		if(a=='M'){
			scanf("%d%d",&x,&y);
			Union(x,y);
		}
		else{
			scanf("%d",&x);
			printf("%d\n",Find(x).d);
		}
	}
	return 0;
}

attention!!!
那个p在自己电脑上如果定义在main函数里输入只能读入两行。也不知道为啥<( ̄ ﹌  ̄)> 。按照我的理解,应该是可以的,因为p这个变量只在main函数里用到过。回头看看书吧。。。(不过找了半天错真的很让人崩溃啊啊啊)
并查集模板

int Find(int x){
	if(dsu[x]<0) return x;
	return dsu[x]=Find(dsu[x]);//路径压缩
}
void Union(int x,int y){
	x=Find(x);//先用根节点覆盖x,y
	y=Find(y);
	if(x==y) return;//判断是否在一个集合
	dsu[x]+=dsu[y];//x为新集合的根节点,跟新集合元素个数
	dsu[y]=x;//更新y的父亲,以前在y集合的点也可以通过y找到x
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值