• [bzoj] 2049 洞穴勘探 || LCT


    原题

    这是一道LCT的板子题。
    至于LCT——link cut tree,也叫动态树,用splay实现动态连边的树。

    预备知识:
    实边:一个非叶节点,向它的儿子中的一个连一条特殊的边,称为实边;该非叶节点向它的其他儿子所引的边均为虚边。注意,对于某些非叶节点,它与它儿子们所连的边可能全部是虚边
    LCT的操作:
    access(x) ——将x到根的路径变成实路径(该实路径的端点为根和x)
    makeroot(x) ——将x变为所在树的根节点
    findroot(x) ——查找x所在树的根节点
    link(x,y) ——连接x与y
    cut(x,y) ——切断x与y的边

    这道题询问连通性,所以只要findroot是否一样即可
    AC代码:

    #include<cstdio>
    #include<algorithm>
    #define N 100010
    #define which(u) (ls[fa[(u)]]==(u))
    #define isroot(u) (!fa[(u)] || (ls[fa[(u)]]!=(u) && rs[fa[u]]!=(u)))
    using namespace std;
    int n,m,fa[N],ls[N],rs[N];
    bool rev[N];
    char s[20];
    
    void rotate(int u)
    {
        int v=fa[u],w=fa[v],b=which(u)?rs[u]:ls[u];
        if (!isroot(v)) (which(v)?ls[w]:rs[w])=u;
        which(u)?(ls[v]=b,rs[u]=v):(rs[v]=b,ls[u]=v);
        fa[u]=w,fa[v]=u;
        if (b) fa[b]=v;
    }
    
    void pushdown(int u)
    {
        if (!rev[u]) return ;
        rev[ls[u]]^=1;
        rev[rs[u]]^=1;
        swap(ls[u],rs[u]);
        rev[u]=0;
    }
    
    void splay(int u)
    {
        static int stk[N],top;
        stk[top=1]=u;
        while (!isroot(stk[top])) stk[top+1]=fa[stk[top]],top++;
        while (top) pushdown(stk[top--]);
        while (!isroot(u))
        {
    	if (!isroot(fa[u]))
    	{
    	    if (which(u)==which(fa[u])) rotate(fa[u]);
    	    else rotate(u);
    	}
    	rotate(u);
        }
    }
    
    void access(int u)
    {
        int v=0;
        while (u)
        {
    	splay(u);
    	rs[u]=v;
    	v=u;
    	u=fa[u];
        }
    }
    
    void makeroot(int u)
    {
        access(u);
        splay(u);
        rev[u]^=1;
    }
    
    int findroot(int u)
    {
        access(u);
        splay(u);
        while (pushdown(u),ls[u]) u=ls[u];
        splay(u);
        return u;
    }
    
    void link(int u,int v)
    {
        makeroot(v);
        fa[v]=u;
    }
    
    void cut(int u,int v)
    {
        makeroot(u);
        access(v);
        splay(v);
        ls[v]=fa[u]=0;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        while (m--)
        {
    	int u,v;
    	scanf("%s",s+1);
    	scanf("%d%d",&u,&v);
    	if (s[1]=='C') link(u,v);
    	else if (s[1]=='Q') findroot(u)==findroot(v)?puts("Yes"):puts("No");
    	else cut(u,v);
        }
        return 0;
    }
    
  • 相关阅读:
    Java集合(二)-Set集合
    Java集合类
    Java构造器和初始化块
    学习OpenStack-Neutron网络服务
    Error response from daemon: Get https://index.docker.io/v1/search?q=tomcat&n=25: net/http: TLS handshake timeout
    学习OpenStack-Nova计算服务
    学习OpenStack-Glance组件部署
    报错:rsync同步报错
    报错:创建nginx镜像时出现报错
    报错:重启Docker报错如何解决
  • 原文地址:https://www.cnblogs.com/mrha/p/8468751.html
Copyright © 2020-2023  润新知