Description
M X Y : Put the whole pile containing block X up to the pile containing Y. If X and Y are in the same pile, just ignore this command.
C X : Count the number of blocks under block X
You are request to find out the output for each C operation.
Input
Output
Sample Input
6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4
Sample Output
1
0
2
今天打比賽前寫的一道帶權並查集
題意 搬磚頭 把包含有 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;
}
現在也找不到什麼帶權並查集的題了 也就發了兩篇博客 總的來說 帶權並查集的核心在於 延遲更新
建圖的時候理清楚合併的集合的關係就好辦了