POJ 1988 : Cube Stacking - 简单并查集

来源:互联网 发布:three.js webgl 编辑:程序博客网 时间:2024/06/11 00:49

题意:

N(N<=30,000)堆方块,开始每堆都是一个方块。方块编号1–N.有以下两种操作:M x y :表示把方块x所在的堆,拿起来叠放到y所在的堆上。C x : 问方块x下面有多少个方块。操作最多有P (P<=100,000)次。对每次C操作,输出结果。

输入:

M x y :表示把方块x所在的堆,拿起来叠放到y所在的堆上。

C x : 问方块x下面有多少个方块。

输出:

C的结果。

思路:

除了par数组,还要开设辅助数组:

sum[]:记录每堆一共有多少方块,par[a] = a, sum[a]表示a所在的堆的方块数目。

under[] under[i]表示第i个方块下面有多少个方块。under数组在堆合并和路径压缩的时候都要更新。


小结:并查集有两种,一种是关系式,一种是数量式。这里是后者。需要开辅助数组求解。


闲话二三:

这些天事情真多,写着写着总是错,参考着前人的,终于A掉了。

#include<iostream>#include<cstdio>using namespace std;const int N=30050;int sum[N],under[N],par[N];void init();void merge(int a,int b);int find_set(int a);int query(int a);int main(){int p;scanf("%d",&p);init();while(p--){char op;int x,y,i;scanf("\n%c",&op);//这种读入方式要学习if(op=='M'){scanf(" %d %d",&x,&y);merge(x,y);}else{scanf("%d",&x);find_set(x);printf("%d\n",under[x]);}}return 0;}void init(){//okfor(int i=1;i<=N;i++){par[i]=i;sum[i]=1;under[i]=0;}}void merge(int a,int b){// C a ba=find_set(a);b=find_set(b);if(a==b) return;par[a]=b;//sum[b]=sum[a];under[a]+=sum[b];//这个函数容易出错,因为a,b相互的操作。并非纯并查集模版类型的操作。sum[b]+=sum[a];}int find_set(int a){int tmp=par[a];if(par[a]!=a){par[a]=find_set(par[a]);under[a]+=under[tmp];}return par[a];}




0 0
原创粉丝点击