【题解】Luogu P2147 [SDOI2008]洞穴勘测

原题传送门

这题用Link-Cut-Tree解决,Link-Cut-Tree详解

我不太会踩爆Link-Cut-Tree的并查集做法qaq

我们用Link-Cut-Tree维护连通性(十分无脑)

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;
 } 

原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/10203159.html

时间: 2024-11-04 05:04:48

【题解】Luogu P2147 [SDOI2008]洞穴勘测的相关文章

P2147 [SDOI2008]洞穴勘测

题目 P2147 [SDOI2008]洞穴勘测 做法 说实话如果你在看这篇题解的话应该也没有人劝你回去打模板吧 My complete code #include<cstdio> #include<cstring> #include<iostream> #include<string> using namespace std; typedef int LL; const LL maxn=1e6; inline LL Read(){ LL x(0),f(1);

BZOJ2049:[SDOI2008]洞穴勘测——题解

http://www.lydsy.com/JudgeOnline/problem.php?id=2049 https://www.luogu.org/problemnew/show/P2147 辉辉热衷于洞穴勘测. 某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假如两个洞穴可以通过一条或者多条通道按一定顺序连接起来,那么这两个洞穴就是连通的,按顺序连接在一起的这些通道则被称之为

[LuoguP2147] [SDOI2008]洞穴勘测 (LCT维护连通性)

题面 传送门:https://www.luogu.org/problemnew/show/P2147 Solution 这题...... 我们可以发现题目要求我们维护一个动态森林,而且只查询连通性.... 显然LCT模板题啊,关于LCT玩法,可以猛戳这里学习 Code #include<iostream> #include<cstdio> #include<vector> using namespace std; long long read() { long long

BZOJ2049 SDOI2008 洞穴勘测 LCT

题意:给定一棵树,维护:1.删除一条边  2.添加一条边  3.询问u和v是否连通 题解:LCT维护连通性 #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; const int MAXN=10000+2; typedef struct NODE{ NODE *ch

BZOJ-2049 [Sdoi2008]洞穴勘测

LCT模版题.... #include <cstdlib> #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cctype> #include <cmath> #define rep(i, l, r) for(int i=l; i<=r; i++) #define clr(x, c) mems

[SDOI2008]洞穴勘测

SOL: LCT维护联通性,当然,启发式合并并查集可能会更好写. #include<bits/stdc++.h> #define N 200007 int rev[N],ch[N][2],f[N],q[N],top; using namespace std; inline void push_down(int x) { if (rev[x]) { rev[ch[x][0]]^=1; rev[ch[x][1]]^=1; rev[x]=0; swap(ch[x][0],ch[x][1]); } }

洛谷P2147 [SDOI2008]Cave 洞穴勘测

题目描述 辉辉热衷于洞穴勘测. 某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假如两个洞穴可以通过一条或者多条通道按一定顺序连接起来,那么这两个洞穴就是连通的,按顺序连接在一起的这些通道则被称之为这两个洞穴之间的一条路径. 洞穴都十分坚固无法破坏,然而通道不太稳定,时常因为外界影响而发生改变,比如,根据有关仪器的监测结果,123号洞穴和127号洞穴之间有时会出现一条通道,有时这

【LCT】BZOJ2049 [SDOI2008]Cave 洞穴勘测

2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 10059  Solved: 4863[Submit][Status][Discuss] Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假如两个洞穴可以通过一条或者多条通道按一定顺序连接起

BZOJ 2049([Sdoi2008]Cave 洞穴勘测-LCT)[Template:LCT]

2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 4809  Solved: 2141 [Submit][Status][Discuss] Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假如两个洞穴可以通过一条或者多条通道按一定顺序连接