zoukankan      html  css  js  c++  java
  • 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
    ",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];//fx到根节点的距离等于当前树的大小 
            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);//这一步是不可少的,因为我们要让每一个点都直接连接跟节点,但给出的z的父节点有可能不是根节点,所以要更新一下
             //            printf("%d
    ",son[find(z)]-dis[z]-1);
                printf("%lld
    ",dis[z]);//dis保存的就是到根的距离 
            }
        }
        return 0;
    }
  • 相关阅读:
    Fanvas是一个把swf转为html5 canvas动画的系统
    截取中文字符防止乱码
    手机号码验证--区号验证--电话号验证--分机号验证--手机号和固定电话二选一--用户名只能为汉字或者英文请--邮箱账号
    laravel5.4学习--laravel基本路由
    laravel5.4学习--laravel目录结构
    laravel5.4学习--laravel安装
    laravel数据迁移
    laravel数据迁移的时候遇到的字符串长度的问题
    TcxLookupComboBox
    Tcxgrid使用例子
  • 原文地址:https://www.cnblogs.com/Accepting/p/11306357.html
Copyright © 2011-2022 走看看