题解 并查集 POJ 1988
题意:有N(N<=30,000)堆方块,开始每堆都是一个方块。方块编号1–
N. 有两种操作:
M x y
: 表示把方块x所在的堆,拿起来叠放到y所在的堆上。
C x :
问方块x下面有多少个方块。
操作最多有
P(P<=100,000)次。对每次C操作,输出结果。
做法:对N个方块设为N个堆。每次进行操作时将两个堆合并。对每个元素的下面方块的
数量进行记录和维护。每次合并时将放在上面的堆的根放在最下面。再用一个数组
记录每个堆的方块总数。
代码:
#include <iostream> #include <cstdio> using namespace std; const int MAX=30000; int par[MAX+10],total[MAX+10],under[MAX+10]; int get(int a) { if(par[a]==a) return a; int t=get(par[a]); under[a]+=under[par[a]]; par[a]=t; return par[a]; } void merge(int a,int b) { int p1=get(a); int p2=get(b); if(p1==p2) return ; par[p2]=p1; under[p2]=total[p1]; total[p1]=total[p1]+total[p2]; } int main() { int T,a,b,i; char ch; for(i=0;i<MAX+10;i++) under[i]=0,par[i]=i,total[i]=1; scanf("%d",&T); while(T--) { scanf("%s",&ch); if(ch=='M') {scanf("%d%d",&a,&b);merge(b,a);} if(ch=='C') {scanf("%d",&a);get(a);printf("%d\n",under[a]);} } return 0; }