POJ1988并查集

并查集本身是一种树形的数据结构,用于处理不相交集合的合并以及查询问题,在使用中常以森林来表示

POJ1988并查集

http://poj.org/problem?id=1988

题意:

有N个方块,有p次操作 分为两种

1  M x y 为将编号为x的方块整体放在含y的方块整体上面

2 C x 询问 x下有多少个方块

讲解详见注释

#include <iostream>
#include <cstdio>
using namespace std;
const int N = 30000 + 5;

int n;
int fa[N], rt[N], block[N];

void init()
{
    for(int i = 1;i < N;i ++)
        fa[i] = i, rt[i] = 0, block[i] = 1;
}

int getf(int x)
{
    int fx = fa[x];

    //如果不是根节点,则进行合并
    if(fa[x] != x)
    {
        //继续找根
        fx = getf(fa[x]);
        //找到过程中更新  rt的信息,即每到一个点更新他到根的距离
        rt[x] += rt[fa[x]];
    }

    fa[x] = fx;
    return fa[x];
}

void Merge(int x,int y)
{
    int dx = getf(x);
    int dy = getf(y);

    fa[dy] = dx;

    //dy 变成了dx的子结点,  那么距离根的长度也要加上原来dx拥有的子结点
    rt[dy] += block[dx];
    //将子结点的所有块加进来
    block[dx] += block[dy];
}

int main()
{
    while(~scanf("%d",&n))
    {
        char op[2];
        int t1, t2;

        //初始化
        init();

        while(n --)
        {
            scanf("%s",op);

            if(op[0] == 'M')
            {
                scanf("%d%d",&t1,&t2);
                //合并t1, t2 即将t1整个箱子块放在t2上
                //从树形结构上来说  t1将变成t2的父节点
                Merge(t1, t2);
            }
            else
            {
                scanf("%d",&t1);
                //t1 的下方块数等于  他所在的一棵树的所有块  减去在它上面的结点的数 再减去它本身 1
                printf("%d\n",block[getf(t1)] - rt[t1] - 1);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Soul_97/article/details/81506270