今天打比赛前写的一道带权并查集

题意 搬砖头 把包含有 a的砖头堆里的 所有砖头 转移到 包含b的砖头堆上 问 K砖头下有几块砖头

思路 :并查集 额外开两个数组 一个记录这堆砖头堆的砖头高度 另一个记录k砖头下有几块砖头 每次合并的时候更新砖头高度 和被合并的砖头堆 最底下砖头 下面有几块砖头 用户find 时更新

AC Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
#include <cstdlib>

using namespace std;
const int maxn=30005;
int root[maxn],under[maxn],height[maxn];
void init(int n)
{
    for(int i=0;i<=n;i++)
        root[i]=i,under[i]=0,height[i]=1;
}

int fin(int x)
{
    if(root[x]==x) return x;
    int rot=root[x];
    root[x]=fin(root[x]);
    under[x]+=under[rot];//递归更新要查找的点
    return root[x];
}

void Union(int u,int v)
{
    int ru=fin(u);
    int rv=fin(v);
    if(ru==rv) return;
    root[ru]=rv;//ru堆的最底下变成了rv
    under[ru]=height[rv];//ru砖头下有rv块砖头
    height[rv]+=height[ru];//更新rv堆砖头高度
}

int main()
{
    char ch[5];
    int u,v,n;
    while(scanf("%d",&n)!=EOF)
    {
        init(n<30000?n:30000);
        for(int i=0;i<n;i++)
        {
            scanf("%s",ch);
            if(ch[0]=='M')
            {
                scanf("%d%d",&u,&v);
                Union(u,v);
            }
            else
            {
                scanf("%d",&u);
                fin(u);//这里必须有   因为算法是延迟更新的    这里如果不查找   就不会更新
                printf("%d\n",under[u]);
            }
        }
    }
    return 0;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Related Posts

带权并查集

HDU3047 Zjnu Stadium

最近一周好好把并查集和最短路走的尽量远一点 再然后就得往RMQ 差分约 Read more…