[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 x=0,f=1; char c=getchar();
    while(!isdigit(c)){if(c==‘-‘) f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-‘0‘;c=getchar();}
    return x*f;
}
const int N=10000+100;
struct LCT
{
    int fa[N],son[N][2],lazy[N],mstack[N],top;
    inline bool isRoot(int x)
    {
        return x!=son[fa[x]][0]&&x!=son[fa[x]][1];
    }
    inline void pushdown(int x)
    {
        if(lazy[x]==0) return;
        lazy[son[x][0]]=!lazy[son[x][0]],swap(son[son[x][0]][0],son[son[x][0]][1]);
        lazy[son[x][1]]=!lazy[son[x][1]],swap(son[son[x][1]][0],son[son[x][1]][1]);
        lazy[x]=0;
    }
    inline void rotate(int x,int type)
    {
        int y=fa[x],z=fa[y];
        if(isRoot(y)==false)    son[z][y==son[z][1]]=x;
        fa[x]=z;
        fa[son[x][type]]=y,son[y][!type]=son[x][type];
        son[x][type]=y,fa[y]=x;
    }
    void splay(int x)
    {
        mstack[top=1]=x;
        for(int i=x;isRoot(i)==false;i=fa[i])
            mstack[++top]=fa[i];
        for(int i=top;i>=1;i--)
            pushdown(mstack[i]);
        while(isRoot(x)==false)
        {
            if(x==son[fa[x]][fa[x]==son[fa[fa[x]]][1]] and isRoot(fa[x])==false)
                rotate(fa[x],x==son[fa[x]][0]),
                rotate(x,x==son[fa[x]][0]);
            else
                rotate(x,x==son[fa[x]][0]);
        }
    }
    void Access(int x)
    {
        for(int t=0;x!=0;t=x,x=fa[x])
            splay(x),son[x][1]=t;
    }
    void MakeRoot(int x)
    {
        Access(x);
        splay(x);
        lazy[x]=!lazy[x],swap(son[x][0],son[x][1]);
    }
    int FindRoot(int x)
    {
        Access(x),splay(x);
        while(son[x][0]!=0)
            pushdown(x),x=son[x][0];
        return x;
    }
    void Link(int x,int y)
    {
        MakeRoot(x);
        fa[x]=y;
    }
    void split(int x,int y)
    {
        MakeRoot(x);
        Access(y),splay(y);
    }
    void Cut(int x,int y)
    {
        split(x,y);
        son[y][0]=fa[x]=0;
    }
}lct;
int n,m;
int main()
{
    n=read(),m=read();

    char OP[15];
    for(int i=1;i<=m;i++)
    {
        scanf("%s",OP+1);
        int u=read(),v=read();
        if(OP[1]==‘C‘)
            lct.Link(u,v);
        else if(OP[1]==‘D‘)
            lct.Cut(u,v);
        else
        {
            if(lct.FindRoot(u)==lct.FindRoot(v))
                printf("Yes\n");
            else
                printf("No\n");
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/GoldenPotato/p/10253764.html

时间: 2024-08-02 16:06:55

[LuoguP2147] [SDOI2008]洞穴勘测 (LCT维护连通性)的相关文章

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

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] [CodeVS1839] [SDOI2008] Cave 洞穴勘测 (LCT)

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

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)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假如两个洞穴可以通过一条或者多条通道按一定顺序连接

【SDOI2008】洞穴勘测 - LCT

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

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

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

[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]); } }

【题解】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() {

BZOJ2049: [SDOI2008]Cave 洞穴勘测 LCT

第一道LCT. 动态维护集合就好了. LCT就是一群链通过父亲关系练成一颗不太连续的树,通过儿子关系组成实边,在这里没有查找单点一说,都是直接拎起来,对于一条链他对外界的有用反馈就是他的链父亲以及需求点的真实位置,而每次cut的时候就会把标记下方好,每次spaly都会找到这个点在这条链中的真实位置,因此这个玄妙的东西就形成了. null不是一定要用只是简化了你的讨论. 千万别忘了这里的spaly的特别之处!!!!!!!! #include<cstring> #include<cstdio