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

题意: 有三种操作,建边,毁边以及查询两个点是否相通,保证任意两个点之间最多只有一条相通的路径,也就是说整个图总是树或森林。

解析: 动态树模板题,另附两个介绍动态树的网址:

https://oi.abcdabcd987.com/summary-of-link-cut-tree/

http://wenku.baidu.com/view/75906f160b4e767f5acfcedb.html

代码

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. using namespace std;
  5. const int maxn=;
  6. struct lct
  7. {
  8. lct *fa,*son[];
  9. int rev;
  10. void pushdown() //把延迟更新的标记清除掉
  11. {
  12. if(!rev) return;
  13. swap(son[],son[]); //翻转,交换左右儿子
  14. son[]->rev^=; son[]->rev^=;
  15. rev=;
  16. }
  17. };
  18. struct LCT
  19. {
  20. lct data[maxn];
  21. lct *null;
  22. void init(int Size=maxn-) //初始化
  23. {
  24. null=data; //null指向首元素
  25. for(int i=;i<=Size;i++)
  26. data[i].son[]=data[i].son[]=data[i].fa=null;
  27. }
  28. bool Same(lct* x,lct* &y) //判断x和x的父亲是否在同一树里
  29. {
  30. return (y=x->fa)!=null&&(y->son[]==x||y->son[]==x);
  31. }
  32. void Rotate(lct* x,int d) //翻转
  33. {
  34. lct* y=x->fa; //x的父亲
  35. y->son[d^]=x->son[d];
  36. if(x->son[d]!=null) x->son[d]->fa=y; //x的子节点的父亲指向y
  37. x->fa=y->fa; //连接
  38. if(y->fa->son[]==y) x->fa->son[]=x;
  39. else if(y->fa->son[]==y) x->fa->son[]=x;
  40. x->son[d]=y;
  41. y->fa=x;
  42. }
  43. void Splay(lct* x)
  44. {
  45. x->pushdown(); //清除标记
  46. lct* y;
  47. while(Same(x,y)) //没有到树的最顶点
  48. {
  49. y->pushdown();
  50. x->pushdown();
  51. Rotate(x,y->son[]==x); //翻转
  52. }
  53. }
  54. lct* Access(lct* u) //打通路径
  55. {
  56. lct *v=null;
  57. for(;u!=null;u=u->fa)
  58. {
  59. Splay(u);
  60. u->son[]=v;
  61. v=u;
  62. }
  63. return v;
  64. }
  65. lct* GetRoot(lct* x) //得到根
  66. {
  67. for(x=Access(x);x->pushdown(),x->son[]!=null;x=x->son[]);
  68. return x;
  69. }
  70. void MakeRoot(lct* x) //使x成为根
  71. {
  72. Access(x)->rev^=;
  73. Splay(x);
  74. }
  75. void Link(lct* x,lct* y) //连接两个点
  76. {
  77. MakeRoot(x);
  78. x->fa=y;
  79. Access(x);
  80. }
  81. void Cut(lct* x,lct* y) //断开两个点
  82. {
  83. MakeRoot(x);
  84. Access(y);
  85. Splay(y);
  86. y->son[]->fa=null;
  87. y->son[]=null;
  88. }
  89. }A;
  90. int N,M;
  91. int main()
  92. {
  93. scanf("%d%d",&N,&M);
  94. A.init(N);
  95. int x,y;
  96. char S[];
  97. while(M--)
  98. {
  99. scanf("%s%d%d",S,&x,&y);
  100. if(S[]=='Q')
  101. {
  102. lct *a=A.GetRoot(A.data+x);
  103. lct *b=A.GetRoot(A.data+y);
  104. if(a!=A.null&&a==b) printf("Yes\n");
  105. else printf("No\n");
  106. }
  107. else if(S[]=='D') A.Cut(A.data+x,A.data+y);
  108. else A.Link(A.data+x,A.data+y);
  109. }
  110. return ;
  111. }

bzoj2049-洞穴勘测(动态树lct模板题)的更多相关文章

  1. BZOJ-2049 Cave洞穴勘测 动态树Link-Cut-Tree (并查集骗分TAT)

    2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MB Submit: 5833 Solved: 2666 [Submit] ...

  2. bzoj 2049: [Sdoi2008]Cave 洞穴勘测 动态树

    2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 3119  Solved: 1399[Submit] ...

  3. hdu 5002 (动态树lct)

    Tree Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submi ...

  4. hdu 5398 动态树LCT

    GCD Tree Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Su ...

  5. HDU 4718 The LCIS on the Tree (动态树LCT)

    The LCIS on the Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Oth ...

  6. 动态树LCT(Link-cut-tree)总结+模板题+各种题目

    一.理解LCT的工作原理 先看一道例题: 让你维护一棵给定的树,需要支持下面两种操作: Change x val:  令x点的点权变为val Query x y:  计算x,y之间的唯一的最短路径的点 ...

  7. 算法复习——LCT(bzoj2049洞穴勘测)

    题目: Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连 ...

  8. [模板] 动态树/LCT

    简介 LCT是一种数据结构, 可以维护树的动态加边, 删边, 维护链上信息(满足结合律), 单次操作时间复杂度 \(O(\log n)\).(不会证) 思想类似树链剖分, 因为splay可以换根, 用 ...

  9. 动态树LCT小结

    最开始看动态树不知道找了多少资料,总感觉不能完全理解.但其实理解了就是那么一回事...动态树在某种意思上来说跟树链剖分很相似,都是为了解决序列问题,树链剖分由于树的形态是不变的,所以可以通过预处理节点 ...

随机推荐

  1. 在线服装零售商Betabrand获得650万美元风投 - 投资风向 - 创业邦

    在线服装零售商Betabrand获得650万美元风投 - 投资风向 - 创业邦 在线服装零售商Betabrand获得650万美元风投

  2. File类的基本操作之InputStream字节输入流

    话不多少,我直接把代码贴上来了.有什么问题请给我留言 package org.mark.streamRW; import java.io.File; import java.io.FileInputS ...

  3. 无语的index hint:手工分配哈希区,5小时不出结果,优化后20分钟

    同事说,有个语句5个小时不出结果,叫我帮忙看看,于是叫同事发过来.不看不知道,一看吓一跳,3个表关联,强制使用了2个index hint,当中一个表9g,一个表67g,另一个小表40Mb.开发者,总以 ...

  4. 转载:android——eclipse如何去除Ctrl+shift+R组合键查找到的.class文件

    转载自:http://blog.csdn.net/virgilli/article/details/22500409 AS里面的build文件下一堆的.class 文件,当你要定位资源文件的时候,有些 ...

  5. Angular单页应用&AngularJS内部实现原理

    回顾 自定义指令 登录后获取登录信息session 首先在登录验证的时候保存一个user 在学生管理页面中运用ajax调用获取到登录的用户信息 对注销按钮添加点击事件:调用ajax在表现层给user赋 ...

  6. ios按钮点击时的灰色框

    a,button,input,textarea{-webkit-tap-highlight-color: rgba(0,0,0,0;)}

  7. Android--------- SD卡存储文件报错解决

    ##文件找不到 1.没有写write权限 2.没有判断文件夹是否存在,不存在则创建

  8. android码农神器 偷懒工具 android懒人框架 LoonAndroid 3 讲解

    LoonAndroid 3.0 Loonandroid是一个注解框架,不涉及任何UI效果,目的是一个功能一个方法,以方法为最小颗粒度对功能进行拆解.把功能傻瓜化,简单化,去掉重复性的代码,隐藏复杂的实 ...

  9. 学习CAS实现SSO单点登录

    学习CAS实现SSO单点登录 网上找了几篇比较详细的教程,在这记录一下: 原理: CAS实现SSO单点登录原理 教程: 1.CAS实现单点登录(SSO)经典完整教程 2.SSO之CAS单点登录实例演示 ...

  10. linux管理员切换与管理员密码第一次设置

    在终端输入su - root回车来切回到超级管理员,Ubuntu的默认超级管理员root密码是随机的,即每次开机都有一个新的root密码.我们可以在终端输入命令 sudo passwd,然后输入当前用 ...