zoukankan      html  css  js  c++  java
  • 【BZOJ2049】【SDOI2008】洞穴勘测 [LCT]

    洞穴勘测

    Time Limit: 10 Sec  Memory Limit: 259 MB
    [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

      100%的数据满足n≤10000, m≤200000

    Main idea

      若干操作,加入一条边,删去一条边,查询两点是否连通。

    Solution

      LCT模板题。

    Code

      1 #include<iostream>  
      2 #include<algorithm>  
      3 #include<cstdio>  
      4 #include<cstring>  
      5 #include<cstdlib>  
      6 #include<cmath>  
      7 using namespace std;  
      8     
      9 const int ONE=200001;
     10 
     11 int n,T;
     12 int u,v;
     13 char ch[10];
     14 
     15 
     16 int get() 
     17 { 
     18         int res,Q=1;    char c;
     19         while( (c=getchar())<48 || c>57)
     20         if(c=='-')Q=-1;
     21         if(Q) res=c-48; 
     22         while((c=getchar())>=48 && c<=57) 
     23         res=res*10+c-48; 
     24         return res*Q; 
     25 }
     26 
     27 namespace LCT
     28 {
     29         int lc[ONE],rc[ONE],fa[ONE];
     30         int hasRev[ONE];
     31         
     32         int is_root(int x)
     33         {
     34             return (lc[fa[x]]!=x && rc[fa[x]]!=x);
     35         }
     36         
     37         void tag_rev(int x)
     38         {
     39             hasRev[x]^=1;
     40             swap(lc[x],rc[x]); 
     41         }
     42         
     43         void tag_down(int x)
     44         {
     45             if(hasRev[x])
     46             {
     47                 tag_rev(lc[x]);
     48                 tag_rev(rc[x]);
     49                 hasRev[x]=0;
     50             }
     51         }
     52         
     53         void Turn(int x)
     54         {
     55             int y=fa[x],z=fa[y];
     56             int b= x==lc[y]?rc[x]:lc[x];
     57             
     58             fa[x]=z;    fa[y]=x;
     59             if(b) fa[b]=y;
     60             
     61             if(z)
     62             {
     63                 if(y==lc[z]) lc[z]=x;
     64                 else
     65                 if(y==rc[z]) rc[z]=x;
     66             }
     67             
     68             if(x==lc[y]) rc[x]=y,lc[y]=b;
     69             else
     70             if(x==rc[y]) lc[x]=y,rc[y]=b;
     71             
     72         }
     73         
     74         void Splay(int x)
     75         {
     76             static int anc[ONE];
     77             int anc_num=0;
     78             anc[++anc_num]=x;
     79             for(int i=x;!is_root(i);i=fa[i]) anc[++anc_num]=fa[i];
     80             while(anc_num>0) tag_down(anc[anc_num--]);
     81             
     82             while(!is_root(x))
     83             {
     84                 if(!is_root(fa[x]))
     85                 {
     86                     if( (lc[fa[x]]==x) == (lc[fa[fa[x]]]==fa[x]) )
     87                     Turn(fa[x]);
     88                     else Turn(x);
     89                 }
     90                 Turn(x);
     91             }    
     92         }
     93         
     94         void access(int x)
     95         {
     96             for(int p=x,q=0; p; q=p,p=fa[p])
     97             {
     98                 Splay(p);
     99                 rc[p]=q;
    100             }
    101         }
    102         
    103         void make_root(int x)
    104         {
    105             access(x);    Splay(x);    tag_rev(x);
    106         }
    107         
    108         void link(int x,int y)
    109         {
    110             make_root(x);    fa[x]=y;
    111         }
    112         
    113         void cut(int x,int y)
    114         {
    115             make_root(x);    access(y);    Splay(y);
    116             fa[x]=lc[y]=0;
    117         }
    118         
    119         int PD(int x,int y)
    120         {
    121             make_root(x);    access(y);    Splay(y);
    122             int pd=0;
    123             for(int i=x;i;i=fa[i])
    124             {
    125                 if(i==y)
    126                 {
    127                     pd=1;
    128                     break;
    129                 }
    130             }
    131             return pd;
    132         }
    133 }
    134 
    135 int main()
    136 {      
    137         n=get();    T=get();
    138         while(T--)
    139         {
    140             scanf("%s",ch);
    141             u=get();    v=get();
    142             if(ch[0]=='C') LCT::link(u,v);
    143             if(ch[0]=='D') LCT::cut(u,v);
    144             if(ch[0]=='Q')
    145             {
    146                 int x=LCT::PD(u,v);
    147                 if(!x) printf("No");
    148                 else printf("Yes");
    149                 printf("
    ");
    150             }
    151         }
    152 }
    View Code
  • 相关阅读:
    webpack常用插件及作用
    函数柯里化
    防抖和节流
    实现深拷贝
    实现new操作符
    关于js中断ajax请求
    从输入 URL 到页面加载完成,发生了什么?
    vue路由传参params和query的区别
    input输入框限制(座机,手机号码)
    判断当前页面是不是用户正在浏览的页面
  • 原文地址:https://www.cnblogs.com/BearChild/p/6429799.html
Copyright © 2011-2022 走看看