PKU 1988 Cube Stacking 并查集

题目意思是有30000个cube,每次执行

M I J,就是将有I 的一堆放在有J的一堆上面

执行

C I 询问I的下面有几个cube

不会出现同一堆的转移这种情况

 

    由于使用并查集,记录了秩的大小,既每一个真根下的cube个数,故down值是很容易求的。所以要解决的,就是从节点到真根的路径的节点数,故堆下的cube个数为down[ root ] - up[i] - 1( root 为i的真根 )

 

AC code

Memory: 508K Time: 282MS

 

#include <iostream>
using namespace std;

const int NMAX = 30050;
int P,i,j;
int father[NMAX],up[NMAX],down[NMAX];

void makeset()
{
    for( i=1; i<=30000; i++ ){
         father[i] = i;
         up[i] = 0;
         down[i] = 1;
    } 
}

int find( int x )
{
    if( x != father[x] ){
        int temp = father[x];
        father[x] = find( father[x] ); 
        up[x] += up[temp]; //路径压缩同时加上父节点的up数
    }
    return father[x];
}

void link( int x , int y )
{
    x = find( x );
    y = find( y );
    father[y] = x;
    up[y] = down[x] ; //up 数 等于 down的数目
    down[x] += down[y];
}

void move()
{
    int x , y ;
    scanf( "%d %d", &x , &y ) ;
    link( x , y );
}

void ask()
{
    int Qes;
    scanf( "%d", &Qes);
    int root = find( Qes );
    printf( "%d/n", down[root] - up[Qes] - 1 ) ;
}

int main()
{
    scanf( "%d", &P );
    getchar();
    makeset();
    while( P -- ){
        char c = getchar();
        if( c == 'M' ) move();
        else ask();
        getchar();
    } 
    return 0;
}
这里有个不错的操作,既father[y] = x ; up[y] = down[x];这样就使得两堆东西合并了一起,但之前y堆下的元素依然指向y
而不是指向x,在询问的过程中会进行一次路径压缩,所以会运行up[x] += up[ father[x] ],导致数的up值正确无误。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值