今天打比赛前写的一道带权并查集
题意 搬砖头 把包含有 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;
}