[US Open 2004][luogu2342] 叠积木 [带权并查集]

题面

洛谷传送门

思路

学了4年多OI,第一次知道还有带权并查集这个东西

wtcl

这个玩意儿的原理和详细实现,可以参考这个博客:带权并查集传送门

这道题,就是在带权并查集的基础上,加个维护每个集合的大小。

并查集往每堆积木的底部那个上面合并(也就是根是最底下的积木),合并的时候把儿子的value设定成父亲的size即可

Code

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cassert>
#define ll long long
using namespace std;
inline int read(){
    int re=0,flag=1;char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-') flag=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
    return re*flag;
}
int n=30000,m,f[100010],siz[100010],val[100010];
inline int find(int x){//带权并查集的路径压缩+权值维护
    if(x==f[x]) return x;
    int tmp=f[x];
    f[x]=find(f[x]);
    val[x]+=val[tmp];
    return f[x];
}
int main(){
    m=read();int i;
    char s[10];int t1,t2,x,y;
    for(i=1;i<=n;i++) f[i]=i,siz[i]=1,val[i]=0;
    while(m--){
        scanf("%s",s);
        if(s[0]=='M'){
            t1=read();t2=read();
            x=find(t1);
            y=find(t2);
            f[x]=y;//合并到底部
            val[x]=siz[y];//权值和集合大小的关系
            siz[y]+=siz[x];
        }
        else{
            t1=read();
            x=find(t1);
            printf("%d\n",val[t1]);
        }
    }
}
            

猜你喜欢

转载自www.cnblogs.com/dedicatus545/p/11782867.html