首页 > 代码库 > poj-1988-Cube Stacking

poj-1988-Cube Stacking

题目大意:有n个独立的磁铁(1-n标号)放在桌上,一个人对这个n堆进行移动操作,然后另外一个人进行询问。

规则:M a b 编号为a的磁铁放在编号为b的磁铁的顶端’

    :C  a   询问在磁铁a下面的磁铁的数目!


分析:利用并查集,每一堆磁铁看作一个集合,“M a b”就是将a归并到b的上面,每个集合都是有序的,设定三个变量

              f:根节点,初始化时为本身;

            all:以该节点为根的集合的元素个数;

            num:该点到其根节点的距离(之间的元素个数);

        那么all[f[a]]-num[a]-1就是以a节点为根节点的集合所含有的元素个数!         (即磁铁个数!!!)

代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=52014;
int n,num[maxn],all[maxn],f[maxn];
void init()
{
    for(int i=1; i<maxn; i++)
    {
        f[i]=i;
        all[i]=1;//此时只有根节点自己一个!
        num[i]=0;
    }
}
int find(int x)
{
    if(f[x]!=x)
    {
        int te=f[x];
        f[x]=find(f[x]);
        num[x]+=num[te];
    }
    return f[x];
}
void unity(int a,int b)
{
    int x=find(a),y=find(b);
    f[y]=x;//a的根节点是b的根节点的父节点!!!
    num[y]=all[x];//更新b的根节点到a的根节点的距离!
    all[x]+=all[y];//因为有新的磁铁集合a放到了b上面,所以更新all[a]!
}
int main()
{
    int t;
    while(cin>>t)
    {
        n=t;
        init();
        while(t--)
        {
            char str[12];
            int a,b;
            cin>>str;
            if(str[0]=='M')
            {
                //把a放在b的上面!
                cin>>a>>b;
                unity(a,b);
            }
            else
            {
                cin>>a;//是压在a下面的磁铁!
                cout<<all[find(a)]-num[a]-1<<endl;//除去a这个磁铁以外!
            }
        }
    }
    return 0;
}





poj-1988-Cube Stacking