• bzoj 2049: [Sdoi2008]Cave 洞穴勘测


    地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2049

    题目:

    2049: [Sdoi2008]Cave 洞穴勘测

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 9479  Solved: 4566
    [Submit][Status][Discuss]

    Description

    辉辉热衷于洞穴勘测。某天,他按照地图来到了一片被标记为JSZX的洞穴群地区。经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴。假如两个洞穴可以通过一条或者多条通道按一定顺序连接起来,那么这两个洞穴就是连通的,按顺序连接在一起的这些通道则被称之为这两个洞穴之间的一条路径。洞穴都十分坚固无法破坏,然而通道不太稳定,时常因为外界影响而发生改变,比如,根据有关仪器的监测结果,123号洞穴和127号洞穴之间有时会出现一条通道,有时这条通道又会因为某种稀奇古怪的原因被毁。辉辉有一台监测仪器可以实时将通道的每一次改变状况在辉辉手边的终端机上显示:如果监测到洞穴u和洞穴v之间出现了一条通道,终端机上会显示一条指令 Connect u v 如果监测到洞穴u和洞穴v之间的通道被毁,终端机上会显示一条指令 Destroy u v 经过长期的艰苦卓绝的手工推算,辉辉发现一个奇怪的现象:无论通道怎么改变,任意时刻任意两个洞穴之间至多只有一条路径。因而,辉辉坚信这是由于某种本质规律的支配导致的。因而,辉辉更加夜以继日地坚守在终端机之前,试图通过通道的改变情况来研究这条本质规律。然而,终于有一天,辉辉在堆积成山的演算纸中崩溃了……他把终端机往地面一砸(终端机也足够坚固无法破坏),转而求助于你,说道:“你老兄把这程序写写吧”。辉辉希望能随时通过终端机发出指令 Query u v,向监测仪询问此时洞穴u和洞穴v是否连通。现在你要为他编写程序回答每一次询问。已知在第一条指令显示之前,JSZX洞穴群中没有任何通道存在。

    Input

    第一行为两个正整数n和m,分别表示洞穴的个数和终端机上出现过的指令的个数。以下m行,依次表示终端机上出现的各条指令。每行开头是一个表示指令种类的字符串s("Connect”、”Destroy”或者”Query”,区分大小写),之后有两个整数u和v (1≤u, v≤n且u≠v) 分别表示两个洞穴的编号。

    Output

    对每个Query指令,输出洞穴u和洞穴v是否互相连通:是输出”Yes”,否则输出”No”。(不含双引号)

    Sample Input

    样例输入1 cave.in
    200 5
    Query 123 127
    Connect 123 127
    Query 123 127
    Destroy 127 123
    Query 123 127
    样例输入2 cave.in

    3 5
    Connect 1 2
    Connect 3 1
    Query 2 3
    Destroy 1 3
    Query 2 3



    Sample Output

    样例输出1 cave.out
    No
    Yes
    No


    样例输出2 cave.out

    Yes
    No

    HINT

    数据说明 10%的数据满足n≤1000, m≤20000 20%的数据满足n≤2000, m≤40000 30%的数据满足n≤3000, m≤60000 40%的数据满足n≤4000, m≤80000 50%的数据满足n≤5000, m≤100000 60%的数据满足n≤6000, m≤120000 70%的数据满足n≤7000, m≤140000 80%的数据满足n≤8000, m≤160000 90%的数据满足n≤9000, m≤180000 100%的数据满足n≤10000, m≤200000 保证所有Destroy指令将摧毁的是一条存在的通道本题输入、输出规模比较大,建议cc++选手使用scanf和printf进行IO操作以免超时

    思路:

      测lct的模板题。

    /**************************************************************
        Problem: 2049
        User: weeping
        Language: C++
        Result: Accepted
        Time:1936 ms
        Memory:3644 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
     
    using namespace std;
     
    struct Link_Cut_Tree
    {
        static const int MAXN = 100000 + 7;
     
        int ch[MAXN][2], fa[MAXN], rev[MAXN], sz[MAXN];
        int sk[MAXN];
     
        bool isroot(int x)
        {
            return ch[fa[x]][0] != x && ch[fa[x]][1] != x;
        }
     
        void reverse(int x)
        {
            rev[x] ^= 1, swap(ch[x][0],ch[x][1]);
        }
     
        void update(int x)
        {
            sz[x] = ch[x][0] +  ch[x][1] +1;
        }
     
        void push_down(int x)
        {
            if(!rev[x]) return ;
            if(ch[x][0]) reverse(ch[x][0]);
            if(ch[x][1]) reverse(ch[x][1]);
            rev[x]=0;
        }
     
        void rotate(int x)
        {
            int f = fa[x], gf = fa[f];
            int t1 = ( x != ch[f][0]), t2 = ( f != ch[gf][0]), tmp = ch[x][1^t1];
            if(!isroot(f)) ch[gf][0^t2] = x;
            fa[tmp] = f, fa[x] = gf, ch[x][1^t1] = f, fa[f] = x, ch[f][0^t1] = tmp;
            update(f);
        }
     
        void splay(int x)
        {
            int top = 0;
            sk[++top] = x;
            for(int i = x; !isroot(i); i = fa[i])   sk[++top] = fa[i];
            while(top)  push_down(sk[top--]);
            for(int f = fa[x], gf = fa[f]; !isroot(x); rotate(x), f = fa[x],gf = fa[f])
            if(!isroot(f))
                rotate((x==ch[f][0]) ^ (f==ch[gf][0]) ? x : f);
            update(x);
        }
     
        void access(int x)
        {
            for(int p = 0; x; p = x, x = fa[x])
                splay(x), ch[x][1] = p, update(x);
        }
     
        void makeroot(int x)
        {
            access(x), splay(x), reverse(x);
        }
     
        int findroot(int x)
        {
            access(x), splay(x);
            while(ch[x][0]) x = ch[x][0];
            return x;
        }
        void link(int x,int y)
        {
            makeroot(x), fa[x] = y;
        }
     
        void cut(int x,int y)
        {
            makeroot(x), access(y), splay(y);
            if(ch[y][0] == x)   ch[y][0] = fa[x] = 0;
            update(y);
        }
     
    }lct;
     
    char ss[100];
    int main(void)
    {
        int n,m;
        cin>>n>>m;
        while(m--)
        {
            int x,y;
            scanf("%s%d%d",ss,&x,&y);
            if(ss[0]=='Q')
            {
                if(lct.findroot(x)==lct.findroot(y))
                    printf("Yes
    ");
                else
                    printf("No
    ");
            }
            else if(ss[0]=='C')
                lct.link(x,y);
            else
                lct.cut(x,y);
        }
        return 0;
    }
  • 相关阅读:
    HTTP协议
    Python学习--装饰器、列表生成式、生成器、map filter、json处理
    Python学习--多线程&多进程
    Python学习--发送邮件
    Python学习--异常处理
    【第五节】【Python学习】【configparser模块】
    【第一节】【shell脚本】【文件里的内容与变量中的内容大小写替换】
    【Python】【多线程多进程】
    【Selenium学习】【拖动滚动条】
    【Python】【异常的获取与处理】
  • 原文地址:https://www.cnblogs.com/weeping/p/7602615.html
Copyright © 2020-2023  润新知