POJ 1988 Cube Stacking

Posted accepting

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1988 Cube Stacking相关的知识,希望对你有一定的参考价值。

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
思路:第一次遇见带权并查集问题,,看了好久才晃晃呼呼的明白一丢丢

#include<iostream>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=1E5+7;
const int nn=30000+10;

int son[N];//表示当前树的大小 
int father[N];
int dis[N];//表示到根结点的距离

int find(int  x)
    if(father[x]==x)
        return  x;
    else 
        int k=father[x];
        father[x]=find(father[x]);
        dis[x]+=dis[k];//这里主要就是起传递作用,因为我们在join函数中对根节点动了手脚,所以我可以采取这样的方式让所有节点都和根节点做同样的变化
        return father[x];
    


void join(int x,int y)
    int fx=find(x),fy=find(y);    
    if(fx!=fy)
        father[fy]=fx;
        dis[fy]=son[fx];//指的是根结点fy到总根节点fx的距离等于fx树的大小 
        son[fx]+=son[fy];//因为又来了几个新元素,,所以更新一下树的大小
    


void inint()
    memset(dis,0,sizeof(dis));
    for(int i=1;i<nn;i++)
        father[i]=i;
        son[i]=1;
    

int main()
    int n;
    inint();
    scanf("%d",&n);
    while(n--)
        char s[10];
        scanf("%s",s);
        if(s[0]==M)
            int x,y;
            scanf("%d%d",&x,&y);
            join(x,y);
        
        else 
            int z;
            scanf("%d",&z);
            printf("%d\n",son[find(z)]-dis[z]-1);//find(z)是根节点。son[find(z)]是树的总长度,dis[z]是Z到根节点的距离,相减后就是Z到末尾的个数,在减去-1,就是减去z
        
    
    return 0;
上边的是固定最小的点,然后对跟不断改变根节点,我们还可以固定根节点,然后逐渐往树上加值:
#include<iostream>
#include<cstring> 
#include<cstdio>
using namespace std;
typedef long long ll;
const int N= 1e5+7;
const int nn=30000+10;
ll fa[N];
ll dis[N];
ll son[N];
ll find(int x)
    if(x==fa[x])
        return fa[x];
    else 
        int k=fa[x];
        fa[x]=find(k);
        dis[x]+=dis[k];
        return fa[x];
    

void join(int x,int y)
    ll fx=find(x),fy=find(y);
    if(fx!=fy)
        fa[fx]=fy;//这里我们让fy做根节点 
        dis[fx]=son[fy];
        son[fy]+=son[fx];
    



void inint()
    memset(dis,0,sizeof(dis));
    for(int i=1;i<nn;i++)
        son[i]=1;
        fa[i]=i;
     




int main()
    int n;
    inint();
    scanf("%d",&n);
    while(n--)
        char s[10];
        scanf("%s",s);
        if(s[0]==M)
            int x,y;
            scanf("%d%d",&x,&y);
            join(x,y);
        
        else 
            int z;
            scanf("%d",&z);
            find(z);//这一步是不可少的,因为我们要让每一个点都直接连接跟节点,但给出的值得父节点
            //可能不是根节点,所以我们跟新一下 
//            printf("%d\n",son[find(z)]-dis[z]-1);
            printf("%lld\n",dis[z]);//dis保存的就是到根的距离 
        
    
    return 0;

 

以上是关于POJ 1988 Cube Stacking的主要内容,如果未能解决你的问题,请参考以下文章

POJ 1988 Cube Stacking

POJ 1988 Cube Stacking

poj1988_Cube Stacking

加权并查集——(POJ1988)Cube Stacking

POJ 1988 Cube Stacking (带权并查集)

poj 1988 Cube Stacking(并查集)