Cube Stacking(并差集深度+结点个数)

Cube Stacking
Time Limit: 2000MS   Memory Limit: 30000K
Total Submissions: 21567   Accepted: 7554
Case Time Limit: 1000MS

Description

Farmer John and Betsy are playing a game with N (1 <= N <= 30,000)identical cubes labeled 1 through N. They start with N stacks, each containing a single cube. Farmer John asks Betsy to perform P (1<= P <= 100,000) operation. There are two types of operations: 
moves and counts. 
* In a move operation, Farmer John asks Bessie to move the stack containing cube X on top of the stack containing cube Y. 
* In a count operation, Farmer John asks Bessie to count the number of cubes on the stack with cube X that are under the cube X and report that value. 

Write a program that can verify the results of the game. 

Input

* Line 1: A single integer, P 

* Lines 2..P+1: Each of these lines describes a legal operation. Line 2 describes the first operation, etc. Each line begins with a 'M' for a move operation or a 'C' for a count operation. For move operations, the line also contains two integers: X and Y.For count operations, the line also contains a single integer: X. 

Note that the value for N does not appear in the input file. No move operation will request a move a stack onto itself. 

Output

Print the output from each of the count operations in the same order as the input file. 

Sample Input

6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4

Sample Output

1
0
2
题意:有n个从1到n编号的箱子,将每个箱子当做一个栈,对这些箱子进行p次操作,每次操作分别为以下两种之一:
           1>输入 M x y:表示将编号为x的箱子所在的栈放在编号为y的箱子所在栈的栈顶.
           2>输入 C x:计算编号为x的所表示的栈中在x号箱子下面的箱子数目.
题解:和龙珠那题一样,坑了半天,写的都醉了。。。
ac代码贴上:
 1 #include<stdio.h>
 2 #include<string.h>
 3 const int MAXN=30010;
 4 int pre[MAXN],s[MAXN],dep[MAXN];//s数组存当前树的节点数; 
 5 int find(int x){
 6     if(x!=pre[x]){
 7         int t=pre[x];
 8         pre[x]=find(pre[x]);
 9         dep[x]+=dep[t];
10     }
11 /*    int i=x,j;
12     while(i!=r){
13         j=pre[i];pre[i]=r;i=j;
14     }*/
15     return pre[x];
16 }
17 void merge(int x,int y){
18     int f1,f2;
19     f1=find(x);f2=find(y);
20 //    printf("%d %d
",f1,f2);
21     if(f1!=f2){
22         pre[f2]=f1;
23         dep[f2]=s[f1]; 
24         s[f1]+=s[f2];
25     }
26 }
27 int main(){
28     int N,x,y;
29     char c[5];//定义成s了,错的啊。。。。 
30     while(~scanf("%d",&N)){
31         for(int i=1;i<=N;i++)pre[i]=i,dep[i]=0,s[i]=1;
32         while(N--){
33         scanf("%s",c);
34         if(c[0]=='M'){
35             scanf("%d%d",&x,&y);
36             merge(x,y);
37         }
38         else {
39             scanf("%d",&x);
40             int px=find(x);
41         //    printf("s[%d]=%d %d
",px,s[px],dep[x]);
42             printf("%d
",s[px]-dep[x]-1);
43             }
44         }
45     }
46     return 0;
47 }

 另一种解法超时:

 1 #include<stdio.h>
 2 #include<string.h>
 3 const int MAXN=300010;
 4 int pre[MAXN],s[MAXN];//s数组存当前树的节点数; 
 5 int find(int x){
 6     while(x!=pre[x])
 7     x=pre[x];
 8     return x;
 9 }
10 void merge(int x,int y){
11     int f1,f2;
12     f1=find(x);f2=find(y);
13     if(f1!=f2){
14         pre[f2]=f1;
15         s[f1]+=s[f2];
16     }
17 }
18 int getdep(int x){
19     int s=0;
20     while(x!=pre[x]){
21         x=pre[x];
22         s++;
23     }
24     return s;
25 }
26 int main(){
27     int N,x,y;
28     char c[5];//定义成s了,错的啊。。。。 
29     while(~scanf("%d",&N)){
30         for(int i=1;i<=N;i++)pre[i]=i,s[i]=1;
31         while(N--){
32         scanf("%s",c);
33         if(c[0]=='M'){
34             scanf("%d%d",&x,&y);
35             merge(x,y);
36         }
37         else {
38             scanf("%d",&x);
39             int px=find(x);
40             int d=getdep(x);
41             printf("%d
",s[px]-d-1);
42             }
43         }
44     }
45     return 0;
46 }
原文地址:https://www.cnblogs.com/handsomecui/p/4842376.html