http://poj.org/problem?id=1988
Time Limit: 2000MS | Memory Limit: 30000K | |
Total Submissions: 19122 | Accepted: 6664 | |
Case Time Limit: 1000MS |
Description
Input
Output
Sample Input
6 M 1 6 C 1 M 2 4 M 2 6 C 3 C 4
Sample Output
1 0 2题意:可以把题目中的意思抽象为栈集合的合并,题目中有两个操作
M 把包含x的栈放在包含y的栈的上面;
C统计包含x的栈中x下面有多少个元素;
分析:此题是并查集路径压缩的典型题目,与前面的种类并查集还有些不同;题目中用到f[],num[],dis[]三个数组,f数组记录i的父节点,num数组记录以i为根的集合有多少个元素,dis记录i到根节点的距离,那么i下面的元素就是x=finde(i);num[x]-dis[i]-1个元素;
程序:
#include"stdio.h" #include"string.h" #include"iostream" #include"map" #include"string" #include"queue" #include"stdlib.h" #include"math.h" #define M 30009 #define eps 1e-10 #define inf 1000000000 #define mod 2333333 using namespace std; int f[M],num[M],dis[M]; int finde(int x) { if(x!=f[x]) { int t=f[x]; f[x]=finde(f[x]); dis[x]+=dis[t]; } return f[x]; } void make(int a,int b) { int x=finde(a); int y=finde(b); if(x!=y) { f[y]=x; dis[y]+=num[x]; num[x]+=num[y]; } } int main() { int n,i,a,b; char str[3]; while(scanf("%d",&n)!=-1) { for(i=1;i<=M+1;i++) { f[i]=i; num[i]=1; dis[i]=0; } while(n--) { scanf("%s",str); if(str[0]=='M') { scanf("%d%d",&a,&b); make(a,b); } else { scanf("%d",&a); int x=finde(a); printf("%d\n",num[x]-dis[a]-1); } } } }