POJ2377 (详解) 用并查集实现最大生成树(速度较快)

来源:互联网 发布:三国志13运行速度优化 编辑:程序博客网 时间:2024/06/14 17:21

#include<iostream>
#include<stdlib.h>
using namespace std;

const int Max = 30050;
int pa[Max], num[Max], under[Max]; 
  // num[x]用于根节点x记录集合的元素数量,集合其他元素的num[]以后不会用到。
  // under[x]用于记录集合元素x与根节点元素的位置差值,由于根节点的under[]为0,
  //故under[x]即为元素x以下的元素数量。
  
void make_set(int n) //初始化,每个节点的父节点就是自己本身
{
    for(int x = 1; x <= n; x ++)
  {
        pa[x] = x;
        num[x] = 1;
        under[x] = 0;
    }
}

int find_set(int x) //找最终的父节点
{

    int tmp = pa[x];
    if(x != pa[x])   //如果x不是最终的父节点
  {
        pa[x] = find_set(pa[x]); //继续向下寻找最终父节点,并将该节点指向最终父节点(并查集中的优化)
        under[x] += under[tmp];   //每个元素与新根节点的位置差值更新
        //上面的一句:在递归查找最终父节点的过程中,其实本来x与其直接父节点之间就差1层,x的直接父节点tmp
    //下面有under[tmp]个元素,所以x下面的元素个数就是上式所示(其实x的直接父节点tmp下面的元素个数
    //也是在递归查找最终父节点的过程中累计起来的)
    }
    return pa[x];
}

void union_set(int x, int y) //合并操作
{
    x = find_set(x);
    y = find_set(y);
    if(x == y) return;  //如果要移动的cube就在目的栈上则返回,不做移动
    pa[x] = y;      //否则就将目的栈栈底作为被移动的栈的父节点
    under[x] += num[y];   //前根节点的差值改变
             //移动后x下面的元素的个数=移动前x下面有的元素的个数+目的栈y中的总的元素的个数
             //因为x所在是栈全部移到目的栈y上面
    num[y] += num[x];   //目的栈元素的总个数=移动前x栈和y栈的元素个数之和
}

int main(){
    int t;
    make_set(30000);
    scanf("%d", &t);
    while(t --)
  {
        char order;
        int x, y;
        scanf("/n%c", &order);     // 要学习这种输入格式,保险点
        if(order == 'M')
    {
            scanf(" %d %d", &x, &y);   // 输入格式
            union_set(x, y);
        }
        else
    {
            scanf(" %d", &x);
            find_set(x);
            printf("%d/n", under[x]);
        }
    }
    return 0;
}

原创粉丝点击