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

原文地址:https://www.cnblogs.com/mrha/p/8468751.html

时间: 2024-08-04 02:38:39

[bzoj] 2049 洞穴勘探 || LCT的相关文章

BZOJ 2049 洞穴勘测

又一道LCT模板题. 如何找是不是在同一棵树上?只要找深度最小的点是不是相同的点即可. 也就是splay最左边的那个点. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxv 10050 #define maxe 20050 using namespace std; int n,m,fath[maxv],size[maxv],tree[ma

[BZOJ 2049] [Sdoi2008] Cave 洞穴勘测 【LCT】

题目链接:BZOJ - 2049 题目分析 LCT的基本模型,包括 Link ,Cut 操作和判断两个点是否在同一棵树内. Link(x, y) : Make_Root(x); Splay(x); Father[x] = y; Cut(x, y) : Make_Root(x); Access(y); 断掉 y 和 Son[y][0]; 注意修改 Son[y][0] 的 isRoot 和 Father 判断 x, y 是否在同一棵数内,我们就看两个点所在树的根是否相同,使用 Find_Root()

BZOJ 2049: [Sdoi2008]Cave 洞穴勘测

二次联通门 : BZOJ 2049: [Sdoi2008]Cave 洞穴勘测 其实指针也不是很慢 我的指针代码能吊打70%的数组 及80%的指针.... /* BZOJ 2049: [Sdoi2008]Cave 洞穴勘测 LCT 连边 删边 查询是否在同一树中时, 只需要一直向上跳 看看树根是否相同就好了 */ #include <cstdio> #include <cstdlib> #include <iostream> #define Max 400009 int

BZOJ 2049: [Sdoi2008]Cave 洞穴勘測 LCT

入门级LCT: 仅仅有 Cut Link 2049: [Sdoi2008]Cave 洞穴勘測 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 3073  Solved: 1379 [id=2049" style="color:blue; text-decoration:none">Submit][Status] Description 辉辉热衷于洞穴勘測.某天,他依照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘

【LCT】【SDOI 2008】【bzoj 2049】Cave 洞穴勘测

2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MB Submit: 4805 Solved: 2139 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)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假如两个洞穴可以通过一条或者多条通道按一定顺序连接

bzoj 2049 Cave 洞穴勘测(LCT)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 动态树入门题,不需要维护任何信息. 我用的是splay,下标实现的lct. 1 #include <iostream> 2 #include <sstream> 3 #include <ios> 4 #include <iomanip> 5 #include <functional> 6 #include <algorith

BZOJ 2049 [Sdoi2008]Cave 洞穴勘测 LCT

题意:链接 方法: LCT 解析: 搞了一下午的LCT,这道题就当做第一道模板?题.然后大概写个理解总结什么的. 首先!splay不要写挂!不要写挂! 然后对于这道题.没有什么奇怪的操作. 只有两个操作,将两个节点连起来,将两个节点之间的连边断开. 每一次询问,询问两个节点是否连通. 听起来挺简单的,一下子就想到了并查集有没有! 然而发现并查集并不可以搞. 也许是我太弱,但是我真的不会并查集的分割. 所以还是老老实实来想LCT. LCT 顾名思义,Link Cut 是其比较有代表性的操作? 首先

【BZOJ 2049】 [Sdoi2008]Cave 洞穴勘测

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