poj 1988 Cube Stacking (并查集)
题意:有N(N<=30,000)堆方块,开始每堆都是一个方块。方块编号1 – N.
有两种操作:
M x y : 表示把方块x所在的堆,拿起来叠放到y所在的堆上。
C x : 问方块x下面有多少个方块。 操作最多有 P (P<=100,000)次。
对每次C操作,输出结果。
#include<stdio.h> const int MAX=31000; int parent[MAX]; int sum[MAX]; //sum[i]表示砖块i所在的堆的砖块数目 int under[MAX]; //under[i]表示砖块i下面有多少砖块 //int t; int GetParent(int a) {//获得a的根,并把a的父节点改为根 if(parent[a]==a) return a; int t=GetParent(parent[a]); under[a]+=under[parent[a]]; parent[a]=t; //将a所在的路径更新(路径压缩) return parent[a]; } void Merge(int a,int b) {//把b所在的堆叠放到a所在的堆上 int n; int pa=GetParent(a); int pb=GetParent(b); if(pa==pb) return ; parent[pb]=pa; under[pb]=sum[pa]; //under[pb]赋值前一定是0,因为parent[pb]=pb; //pb一定是原b所在的堆最底下的 sum[pa]+=sum[pb]; } int main() { int i,p; for(i=0;i<MAX;i++) { parent[i]=i; sum[i]=1; under[i]=0; } scanf("%d",&p); for(i=0;i<p;i++) { char s[20]; int a,b; scanf("%s",s); if(s[0]=='M') { scanf("%d%d",&a,&b); Merge(b,a); } else { scanf("%d",&a); GetParent(a); printf("%d\n",under[a]); } } return 0; }
类似题型: POJ1611 The Suspects n个学生分属m个团体,(0 < n <= 30000 , 0 <= m <= 500) 一个学生可以属于多个团体。一个学生疑似患病,则它所属的整个团体都疑似患病。已知0号学生疑似患病,以及每个团体都由哪些学生构成,求一共多少个学生疑似患病。