【[SDOI2008]洞穴勘测】

本文深入探讨了LCT树(Lazy Cascaded Tree)的数据结构原理及其在动态连通性问题上的高效应用。通过三个核心操作:link(链接)、cut(切割)、findroot(查找根节点),实现对动态变化的森林进行快速维护。文章提供了完整的C++代码实现,展示了如何处理节点间的链接与断开,以及判断两节点是否在同一连通分量中的算法细节。

题目

由于始终保证连通性于是我们可以用\(LCT\)来维护这个森林

三个操作分别是\(link,cut,findroot\)

代码

#include<iostream>
#include<cstdio>
#define maxn 10005
#define re register
inline int read()
{
    char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
char opt[15];
int n,m;
int rev[maxn],fa[maxn],ch[maxn][2],st[maxn];
inline int nroot(int x) {return ch[fa[x]][0]==x||ch[fa[x]][1]==x;}
inline void pushdown(int x) {
    if(!rev[x]) return;
    rev[x]=0,rev[ch[x][0]]^=1,rev[ch[x][1]]^=1;
    std::swap(ch[ch[x][0]][0],ch[ch[x][0]][1]);
    std::swap(ch[ch[x][1]][0],ch[ch[x][1]][1]);
}
inline void rotate(int x) {
    int y=fa[x],z=fa[y],k=ch[y][1]==x,w=ch[x][k^1];
    if(nroot(y)) ch[z][ch[z][1]==y]=x;
    ch[x][k^1]=y,ch[y][k]=w;
    fa[w]=y;fa[y]=x,fa[x]=z;
}
inline void splay(int x) {
    int y=x,top=0;
    st[++top]=x;
    while(nroot(y)) st[++top]=fa[y],y=fa[y];
    while(top) pushdown(st[top--]);
    while(nroot(x)) {
        int y=fa[x];
        if(nroot(y)) rotate((ch[fa[y]][1]==y)^(ch[y][1]==x)?x:y);
        rotate(x);
    }
}
inline void access(int x) {
    for(re int y=0;x;y=x,x=fa[x])
        splay(x),ch[x][1]=y;
}
inline void makeroot(int x) {
    access(x);splay(x);rev[x]^=1;std::swap(ch[x][0],ch[x][1]);
}
inline int findroot(int x) {
    access(x),splay(x);
    while(ch[x][0]) pushdown(x),x=ch[x][0];
    return x;
}
inline void link(int x,int y) {
    makeroot(x);
    if(findroot(y)!=x) fa[x]=y;
}
inline void split(int x,int y) {
    makeroot(x);access(y);splay(y);
}
inline void cut(int x,int y) {
    split(x,y);fa[x]=ch[y][0]=0;
}
int main()
{
    n=read(),m=read();
    int x,y;
    while(m--) {
        scanf("%s",opt);x=read(),y=read();
        if(opt[0]=='D') cut(x,y);
        if(opt[0]=='C') link(x,y);
        if(opt[0]=='Q') puts((findroot(x)==findroot(y))?"Yes":"No");
    }
    return 0;
}

转载于:https://www.cnblogs.com/asuldb/p/10366722.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值