zoukankan      html  css  js  c++  java
  • 【题解】Luogu P2147 [SDOI2008]洞穴勘测

    原题传送门

    Connect操作:把u,v两个点连起来

    Destroy操作:把u,v两个点分开来

    Query操作:判断在这个森林里u的根和v的根是否相等

    #include <bits/stdc++.h>
    #define N 10005
    using namespace std;
    inline int read()
    {
        register int f=1,x=0;register char ch;
        do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
        do{x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
        return f*x;
    }
    inline void Swap(register int &a,register int &b)
    {
        a^=b^=a^=b;
    }
    struct Link_Cut_Tree{
        int c[N][2],fa[N],top,q[N],rev[N];
        inline void pushdown(register int x){
            if(rev[x])
            {
                register int l=c[x][0],r=c[x][1];
                rev[l]^=1,rev[r]^=1,rev[x]^=1;
                Swap(c[x][0],c[x][1]);
            }
        }
        inline bool isroot(register int x)
        {
            return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;
        }
        inline void rotate(register int x)
        {
            int y=fa[x],z=fa[y],l,r;
            l=c[y][0]==x?0:1;
            r=l^1;
            if(!isroot(y))
                c[z][c[z][0]==y?0:1]=x;
            fa[x]=z;
            fa[y]=x;
            fa[c[x][r]]=y;
            c[y][l]=c[x][r];
            c[x][r]=y;
        }
        inline void splay(register int x)
        {
            top=1;
            q[top]=x;
            for(register int i=x;!isroot(i);i=fa[i])
                q[++top]=fa[i];
            for(register int i=top;i;--i)
                pushdown(q[i]);
            while(!isroot(x))
            {
                int y=fa[x],z=fa[y];
                if(!isroot(y))
                    rotate((c[y][0]==x)^(c[z][0]==y)?(x):(y));
                rotate(x);
            }
        }
        inline void access(register int x)
        {
            for(register int t=0;x;t=x,x=fa[x])
            {
                splay(x);
                c[x][1]=t;
            }
        }
        inline void makeroot(register int x)
        {
            access(x);
            splay(x);
            rev[x]^=1;
        }
        inline int findroot(register int x)
        {
            access(x);
            splay(x);
            while(c[x][0])
                x=c[x][0];
            return x;
        }
        inline void split(register int x,register int y)
        {
            makeroot(x);
            access(y);
            splay(y);
        }
        inline void cut(register int x,register int y)
        {
            split(x,y);
            c[y][0]=0;
            fa[x]=0;
        }
        inline void link(register int x,register int y)
        {
            makeroot(x);
            fa[x]=y;	
        }	
    }T;
    int n,m;
    int main()
    {
        n=read(),m=read();
        char ch[10];
        while(m--)
        {
            scanf("%s",ch);
            if(ch[0]=='C')
            {
                int x=read(),y=read();
                T.link(x,y);
            }
            else if(ch[0]=='D')
            {
                int x=read(),y=read();
                T.cut(x,y);
            }
            else
            {
                int x=read(),y=read();
                puts(T.findroot(x)==T.findroot(y)?"Yes":"No");
            }
        }
        return 0;
     } 
    
  • 相关阅读:
    redis之 Redis常用数据类型
    mysql5.6之 传输表空间迁移表或恢复误删除的表
    mysql之 double write 浅析
    网络防火墙实战-基于pfsense(1)
    信息战(四)——战场演练(线段树,树状数组)
    dojo(四):ajax请求
    网络防火墙实战-基于pfsense(2)
    [置顶] 最小生成树Prim算法
    (DP6.1.2.1)UVA 147 Dollars(子集和问题)
    Redis的Time Event与File Event的微妙关系
  • 原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/10203159.html
Copyright © 2011-2022 走看看