首页 > 代码库 > hdu 2818 Building Block(带权并查集)

hdu 2818 Building Block(带权并查集)

题目:

        链接:点击打开链接

题意:

        有N个积木,1到N编号。进行一些操作P次,M:X Y把X积木放到Y的上面,如果X和Y相等请忽略。C:X 计算X积木下的积木数目。

思路:

        带权并查集的题目,定义数组sum[i]表示i积木下面积木的数目。遇到操作M,就把X和Y合并到同一个集合中。我们视每个结点为1个 Pile,其中rank[i]就表示每个Pile处的积木的个数,Initially, there are N piles, and each pile contains one block.所以,rank[]的初始值应该是1。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;


const int N = 30030;


int root[N];
int sum[N],rank[N];
int q;


int findset(int x)
{
    if(x == root[x])
        return x;
    int temp = findset(root[x]);
    sum[x] += sum[root[x]];
    return root[x] = temp;
}


void mergeset(int x,int y)
{
    int fx = findset(x);
    int fy = findset(y);
    if(fx == fy)
        return ;
    root[fx] = fy;
    sum[fx] += rank[fy];//sum
    rank[fy] += rank[fx];//每进行一次M操作,rank的值都要更新。
}


void init()
{
    for(int i=0; i<=30000; i++)
    {
        root[i] = i;
        rank[i] = 1;
        sum[i] = 0;
    }
}
int main()
{
    //freopen("input.txt","r",stdin);
    char ch;
    int x,y,z;
    while(scanf("%d",&q) != EOF)
    {
        init();
        getchar();
        while(q--)
        {
            scanf("%c",&ch);
            getchar();
            if(ch == 'M')
            {
                scanf("%d%d",&x,&y);
                mergeset(x,y);
            }
            else
            {
                scanf("%d",&z);
                findset(z);
                printf("%d\n",sum[z]);
            }
            getchar();
        }
    }
    return 0;
}
---------------------------------------------------------------

战斗,从不退缩;奋斗,永不停歇~~~~~~~~