poj 1988 Cube Stacking (并查集)

题意:有N(N<=30,000)堆方块,开始每堆都是一个方块。方块编号1 – N.

有两种操作:

  M x y : 表示把方块x所在的堆,拿起来叠放到y所在的堆上。

  C x : 问方块x下面有多少个方块。 操作最多有 P (P<=100,000)次。

对每次C操作,输出结果。

#include<stdio.h>
const int MAX=31000;
int parent[MAX];
int sum[MAX];
//sum[i]表示砖块i所在的堆的砖块数目
int under[MAX];
//under[i]表示砖块i下面有多少砖块
//int t;
int GetParent(int a)
{//获得a的根,并把a的父节点改为根
    if(parent[a]==a)
        return a;
    int t=GetParent(parent[a]);
    under[a]+=under[parent[a]];
    parent[a]=t;
    //将a所在的路径更新(路径压缩)
    return parent[a];
}
void Merge(int a,int b)
{//把b所在的堆叠放到a所在的堆上
    int n;
    int pa=GetParent(a);
    int pb=GetParent(b);
    if(pa==pb)
        return ;
    parent[pb]=pa;
    under[pb]=sum[pa];
    //under[pb]赋值前一定是0,因为parent[pb]=pb;
    //pb一定是原b所在的堆最底下的
    sum[pa]+=sum[pb];
}
int main()
{
    int i,p;
    for(i=0;i<MAX;i++)
    {
        parent[i]=i;
        sum[i]=1;
        under[i]=0;
    }
    scanf("%d",&p);
    for(i=0;i<p;i++)
    {
        char s[20];
        int a,b;
        scanf("%s",s);
        if(s[0]=='M')
        {
            scanf("%d%d",&a,&b);
            Merge(b,a);
        }
        else
        {
            scanf("%d",&a);
            GetParent(a);
            printf("%d
",under[a]);
        }
    }
    return 0;
}

 

 

类似题型:
    POJ1611  The Suspects
    n个学生分属m个团体,(0 < n <= 30000 , 0 <= m <= 500) 一个学生可以属于多个团体。一个学生疑似患病,则它所属的整个团体都疑似患病。已知0号学生疑似患病,以及每个团体都由哪些学生构成,求一共多少个学生疑似患病。
原文地址:https://www.cnblogs.com/XDJjy/p/3283690.html