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[maxv][3],x,y,rev[maxv];
int stack[maxv],top=0;
char s[20];
bool isroot(int x)
{
    return tree[fath[x]][1]!=x&&tree[fath[x]][2]!=x;
}
void pushdown(int x)
{
    if (rev[x])
    {
        int ls=tree[x][1],rs=tree[x][2];
        rev[ls]^=1;rev[rs]^=1;rev[x]=0;
        swap(tree[x][1],tree[x][2]);
    }
}
void pushup(int x)
{
    int ls=tree[x][1],rs=tree[x][2];
    size[x]=size[ls]+size[rs]+1;
}
void rotate(int x)
{
    int y=fath[x],z=fath[y],l,r;
    if (tree[y][1]==x) l=1;else l=2;
    r=3-l;
    if (!isroot(y))
    {
        if (tree[z][1]==y) tree[z][1]=x;
        else tree[z][2]=x;
    }
    fath[x]=z;fath[y]=x;fath[tree[x][r]]=y;
    tree[y][l]=tree[x][r];tree[x][r]=y;
    pushup(y);pushup(x);
}
void splay(int x)
{
    top=0;
    stack[++top]=x;
    for (int i=x;!isroot(i);i=fath[i])
        stack[++top]=fath[i];
    for (int i=top;i>=1;i--)
        pushdown(stack[i]);
    while (!isroot(x))
    {
        int y=fath[x],z=fath[y];
        if (!isroot(y))
        {
            if ((tree[y][1]==x)^(tree[z][1]==y)) rotate(x);
            else rotate(y);
        }
        rotate(x);
    }
}
void access(int x)
{
    int regis=0;
    while (x)
    {
        splay(x);
        tree[x][2]=regis;
        regis=x;x=fath[x];
    }
}
void makeroot(int x)
{
    access(x);
    splay(x);
    rev[x]^=1;
}
void link()
{
    scanf("%d%d",&x,&y);
    makeroot(x);
    fath[x]=y;
    splay(x);
}
void cut()
{
    scanf("%d%d",&x,&y);
    makeroot(x);access(y);
    splay(y);tree[y][1]=0;fath[x]=0;
}
int find(int x)
{
    access(x);splay(x);
    int y=x;
    while (tree[y][1]) y=tree[y][1];
    return y;
}
void query()
{
    scanf("%d%d",&x,&y);
    int u=find(x),v=find(y);
    if (u==v)
        printf("Yes\n");
    else printf("No\n");
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) size[i]=1;
    for (int i=1;i<=m;i++)
    {
        scanf("%s",s);
        if (s[0]==‘C‘) link();
        else if (s[0]==‘D‘) cut();
        else if (s[0]==‘Q‘) query();
    }
    return 0;
}
时间: 2024-08-04 02:38:44

BZOJ 2049 洞穴勘测的相关文章

[bzoj] 2049 洞穴勘探 || LCT

原题 这是一道LCT的板子题. 至于LCT--link cut tree,也叫动态树,用splay实现动态连边的树. 预备知识: 实边:一个非叶节点,向它的儿子中的一个连一条特殊的边,称为实边;该非叶节点向它的其他儿子所引的边均为虚边.注意,对于某些非叶节点,它与它儿子们所连的边可能全部是虚边 LCT的操作: access(x) --将x到根的路径变成实路径(该实路径的端点为根和x) makeroot(x) --将x变为所在树的根节点 findroot(x) --查找x所在树的根节点 link(

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)[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: [Sdoi2008]Cave 洞穴勘测(link cut tree)

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

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

【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】

题目链接: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

LCT 哦……LCT的一道更水的裸题,适合学习access,link,cut等基本操作(其实这三个不是在一个层面上的?不要在意这些细节……) 1 /************************************************************** 2 Problem: 2049 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:1920 ms 7 Memory:1480 kb 8 **************

【bzoj 2049】Cave 洞穴勘测

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