[luoguP2147] [SDOI2008]Cave 洞穴勘测(并查集 || lct)
传送门
1.并查集骗分(数据太水,比正解还快。。。)
我们知道,并查集有一步操作叫“路径压缩”,但是本题的并查集我们不能路径压缩,否则就无法进行Destroy操作。那每一步操作我们应该怎么做呢?
对于Connect x y操作,先把x变成集合的根,之后root[x] = y;
对于Destroy x y操作,先把x变成集合的根,此时root[y]必然为x,令root[y] = y即可。
对于Query x y操作,看看x和y所在集合的根是不是一样的就好了。
那么如何把x变成集合的根呢?只要把从x到根路径上的每一条边反向即可,所以不能进行路径压缩。
其实并查集的解法也有用 lct 的思想的。
在这里,并查集中的两点之间的边就表示连接两个洞穴之间的边,非常的直接。。
注意一个细节 : 题目中说——无论通道怎么改变,任意时刻任意两个洞穴之间至多只有一条路径
也就是说不会有环!这也正是能用并查集做的原因之一。
——代码
1 #include <cstdio> 2 #include <iostream> 3 #define N 10001 4 5 int n, m; 6 int f[N]; 7 8 inline int read() 9 { 10 int x = 0, f = 1; 11 char ch = getchar(); 12 for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1; 13 for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; 14 return x * f; 15 } 16 17 inline int find(int x) 18 { 19 while(x ^ f[x]) x = f[x]; 20 return x; 21 } 22 23 inline void make_root(int x, int c) 24 { 25 if(x ^ f[x]) make_root(f[x], x); 26 f[x] = c; 27 } 28 29 int main() 30 { 31 int i, j, x, y, fx, fy; 32 char s[10]; 33 n = read(); 34 m = read(); 35 for(i = 1; i <= n; i++) f[i] = i; 36 for(i = 1; i <= m; i++) 37 { 38 scanf("%s", s); 39 x = read(); 40 y = read(); 41 if(s[0] == 'Q') find(x) == find(y) ? puts("Yes") : puts("No"); 42 else if(s[0] == 'C') make_root(x, x), f[x] = y; 43 else make_root(x, x), f[y] = y; 44 } 45 return 0; 46 }
View Code
2.lct(正解)
就是模板啦
——代码
1 #include <cstdio> 2 #include <iostream> 3 #define N 10001 4 #define swap(x, y) ((x) ^= (y) ^= (x) ^= (y)) 5 6 int n, m; 7 int f[N], rev[N], son[N][2], s[N], size[N]; 8 9 inline int read() 10 { 11 int x = 0, f = 1; 12 char ch = getchar(); 13 for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1; 14 for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; 15 return x * f; 16 } 17 18 inline bool isroot(int x) 19 { 20 return son[f[x]][0] ^ x && son[f[x]][1] ^ x; 21 } 22 23 inline int get(int x) 24 { 25 return son[f[x]][1] == x; 26 } 27 28 inline void pushdown(int x) 29 { 30 if(x && rev[x]) 31 { 32 swap(son[x][0], son[x][1]); 33 if(son[x][0]) rev[son[x][0]] ^= 1; 34 if(son[x][1]) rev[son[x][1]] ^= 1; 35 rev[x] = 0; 36 } 37 } 38 39 inline void rotate(int x) 40 { 41 int old = f[x], oldf = f[old], wh = get(x); 42 43 if(!isroot(old)) 44 son[oldf][son[oldf][1] == old] = x; 45 f[x] = oldf; 46 47 son[old][wh] = son[x][wh ^ 1]; 48 f[son[old][wh]] = old; 49 50 son[x][wh ^ 1] = old; 51 f[old] = x; 52 } 53 54 inline void splay(int x) 55 { 56 int i, fa, t = 0; 57 s[++t] = x; 58 for(i = x; !isroot(i); i = f[i]) s[++t] = f[i]; 59 for(i = t; i >= 1; i--) pushdown(s[i]); 60 for(; !isroot(x); rotate(x)) 61 if(!isroot(fa = f[x])) 62 rotate(get(x) == get(fa) ? fa : x); 63 } 64 65 inline void access(int x) 66 { 67 for(int t = 0; x; t = x, x = f[x]) splay(x), son[x][1] = t; 68 } 69 70 inline void reverse(int x) 71 { 72 access(x); 73 splay(x); 74 rev[x] ^= 1; 75 } 76 77 inline int find(int x) 78 { 79 access(x); 80 splay(x); 81 while(son[x][0]) x = son[x][0]; 82 return x; 83 } 84 85 inline void link(int x, int y) 86 { 87 reverse(x); 88 f[x] = y; 89 splay(x); 90 } 91 92 inline void cut(int x, int y) 93 { 94 reverse(x); 95 access(y); 96 splay(y); 97 son[y][0] = f[x] = 0; 98 } 99 100 int main() 101 { 102 int i, j, x, y; 103 char s[10]; 104 n = read(); 105 m = read(); 106 for(i = 1; i <= m; i++) 107 { 108 scanf("%s", s); 109 x = read(); 110 y = read(); 111 if(s[0] == 'Q') find(x) == find(y) ? puts("Yes") : puts("No"); 112 if(s[0] == 'C') link(x, y); 113 if(s[0] == 'D') cut(x, y); 114 } 115 return 0; 116 }
View Code
转载于:https://www.cnblogs.com/zhenghaotian/p/7018198.html
[luoguP2147] [SDOI2008]Cave 洞穴勘测(并查集 || lct)相关推荐
- bzoj2049 [Sdoi2008]Cave 洞穴勘测
[Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MB Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为J ...
- BZOJ 2049: [Sdoi2008]Cave 洞穴勘测
Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好 ...
- [SDOI2008]Cave 洞穴勘测
题目描述 辉辉热衷于洞穴勘测. 某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假 ...
- bzoj2049 [Sdoi2008]Cave 洞穴勘测——LCT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2049 第二道LCT! 这题是模板题,写了一遍以后感觉对LCT的认识又加深了. 代码如下: # ...
- BZOJ 2049: [Sdoi2008]Cave 洞穴勘测——LCT
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2049 省选之前来切一道数据结构模板题. 题意 这是一道模板题. N个点,M次操作,每次加边/ ...
- bzoj2049: [Sdoi2008]Cave 洞穴勘测
[题意] 给你一个森林,要求支持动态加边删边,并会询问在某一个时刻两点是否联通. [题解] 裸的lct,模版题.第一次写对lct,没写过真的难写.... [代码] 1 #include <ios ...
- bzoj2049 Cave 洞穴勘测 LCT模版
2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MB Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了 ...
- [luogu-P4299] 首都(并查集 + LCT动态维护树的重心 / 维护虚儿子信息)
problem luogu-P4299 solution 本题考察了很经典的模型,运用了很经典的解法. 本题用到了重心的两个性质: 两棵树合并为同一棵树时,新的重心一定在原来两棵树各自重心的路径上. ...
- bzoj 2959: 长跑(LCT+并查集)
2959: 长跑 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 315 Solved: 178 [Submit][Status][Discuss] ...
- [BZOJ2049] [SDOI2008] 洞穴勘测
题目描述 辉辉热衷于洞穴勘测. 某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假 ...
最新文章
- 算法学习之路|完美数列
- Linux给用户添加sudo权限
- 畅通工程,How Many Tables ACM第九天-图论
- 开发教程(四) MIP组件平台使用说明
- 关于uint32_t uint8_t uint64_t 的问题
- electron 打包后 __static_electron开发客户端注意事项(兼开源个人知识管理工具“想学吗”)...
- JS弹出可拖动层,并蒙住页面
- 深度挖掘论文:《Semantic Soft Segmentation》(语义软分割)
- 第 1 章 FreeBSD Install
- Elasticsearch搜索类型(query type)详解
- Linux 命令之 yum 软件仓库
- Structs2文件上传以及预览
- MTK6589反向修改拼包法操作流程
- AmazeUI组件使用和百度地图集成
- iOS_21团购_拼音搜索
- Cubist Artwork
- DNP3 模拟器使用教程
- ABP框架系列之三十一:(Localization-本地化)
- 分布式项目-谷粒商城。
- Hadoop(二)Hive原理解析