[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 的思想的。
在这里,并查集中的两点之间的边就表示连接两个洞穴之间的边,非常的直接。。
注意一个细节 : 题目中说——无论通道怎么改变,任意时刻任意两个洞穴之间至多只有一条路径
也就是说不会有环!这也正是能用并查集做的原因之一。
——代码
#include <cstdio>
#include <iostream>
#define N 10001 int n, m;
int f[N]; inline int read()
{
int x = , f = ;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -;
for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
return x * f;
} inline int find(int x)
{
while(x ^ f[x]) x = f[x];
return x;
} inline void make_root(int x, int c)
{
if(x ^ f[x]) make_root(f[x], x);
f[x] = c;
} int main()
{
int i, j, x, y, fx, fy;
char s[];
n = read();
m = read();
for(i = ; i <= n; i++) f[i] = i;
for(i = ; i <= m; i++)
{
scanf("%s", s);
x = read();
y = read();
if(s[] == 'Q') find(x) == find(y) ? puts("Yes") : puts("No");
else if(s[] == 'C') make_root(x, x), f[x] = y;
else make_root(x, x), f[y] = y;
}
return ;
}
2.lct(正解)
就是模板啦
——代码
#include <cstdio>
#include <iostream>
#define N 10001
#define swap(x, y) ((x) ^= (y) ^= (x) ^= (y)) int n, m;
int f[N], rev[N], son[N][], s[N], size[N]; inline int read()
{
int x = , f = ;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -;
for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
return x * f;
} inline bool isroot(int x)
{
return son[f[x]][] ^ x && son[f[x]][] ^ x;
} inline int get(int x)
{
return son[f[x]][] == x;
} inline void pushdown(int x)
{
if(x && rev[x])
{
swap(son[x][], son[x][]);
if(son[x][]) rev[son[x][]] ^= ;
if(son[x][]) rev[son[x][]] ^= ;
rev[x] = ;
}
} inline void rotate(int x)
{
int old = f[x], oldf = f[old], wh = get(x); if(!isroot(old))
son[oldf][son[oldf][] == old] = x;
f[x] = oldf; son[old][wh] = son[x][wh ^ ];
f[son[old][wh]] = old; son[x][wh ^ ] = old;
f[old] = x;
} inline void splay(int x)
{
int i, fa, t = ;
s[++t] = x;
for(i = x; !isroot(i); i = f[i]) s[++t] = f[i];
for(i = t; i >= ; i--) pushdown(s[i]);
for(; !isroot(x); rotate(x))
if(!isroot(fa = f[x]))
rotate(get(x) == get(fa) ? fa : x);
} inline void access(int x)
{
for(int t = ; x; t = x, x = f[x]) splay(x), son[x][] = t;
} inline void reverse(int x)
{
access(x);
splay(x);
rev[x] ^= ;
} inline int find(int x)
{
access(x);
splay(x);
while(son[x][]) x = son[x][];
return x;
} inline void link(int x, int y)
{
reverse(x);
f[x] = y;
splay(x);
} inline void cut(int x, int y)
{
reverse(x);
access(y);
splay(y);
son[y][] = f[x] = ;
} int main()
{
int i, j, x, y;
char s[];
n = read();
m = read();
for(i = ; i <= m; i++)
{
scanf("%s", s);
x = read();
y = read();
if(s[] == 'Q') find(x) == find(y) ? puts("Yes") : puts("No");
if(s[] == 'C') link(x, y);
if(s[] == 'D') cut(x, y);
}
return ;
}
[luoguP2147] [SDOI2008]Cave 洞穴勘测(并查集 || lct)的更多相关文章
- 【bzoj2049】[Sdoi2008]Cave 洞穴勘测——线段树上bfs求可撤销并查集
题面 2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MB Submit: 12030 Solved: 6024 Desc ...
- 【bzoj2049】[Sdoi2008]Cave 洞穴勘测 link-cut-tree
2016-05-30 11:04:51 学习了link-cut-tree 二中神犇封禹的讲义感觉讲的超级清晰易懂啊(没有的可以q窝 算是模板吧 #include<bits/stdc++.h&g ...
- BZOJ 2049: [Sdoi2008]Cave 洞穴勘测 LCT
2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnli ...
- bzoj 2049: [Sdoi2008]Cave 洞穴勘测 动态树
2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 3119 Solved: 1399[Submit] ...
- 【LCT】BZOJ2049 [SDOI2008]Cave 洞穴勘测
2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 10059 Solved: 4863[Submit ...
- BZOJ_2049_[Sdoi2008]Cave 洞穴勘测_LCT
BZOJ_2049_[Sdoi2008]Cave 洞穴勘测_LCT Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由 ...
- bzoj 2049: [Sdoi2008]Cave 洞穴勘测 (LCT)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2049 题面: 2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 1 ...
- BZOJ 2049: [Sdoi2008]Cave 洞穴勘测 (动态树入门)
2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1528 Solved: 644[Submit][ ...
- 2049: [Sdoi2008]Cave 洞穴勘测
2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MB Submit: 7475 Solved: 3499 [Submi ...
随机推荐
- [转]C++中sizeof(struct)怎么计算?
版权属于原作者,我只是排版. 1. sizeof应用在结构上的情况 请看下面的结构: struct MyStruct{ double dda1; char dda; int type;}; 对结构My ...
- 2018.5.4 AndroidStudio遇到的问题
新建项目初出现异常报错 Error:Execution failed for task ':app:preDebugAndroidTestBuild'. > Conflict 发生这类型的错误, ...
- python_90_hashlib模块
#用于加密相关的操作,3.x里代替了2.x中的md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法 import hashlib ...
- linux文本处理工具及正则表达式
cat命令:查看文本内容 cat [选项]... [文件]... -E 显示行结束符 -n 显示文本内容时显示行号 -A 显示所以控制符 -b 非空行编号 -s 压缩连 ...
- CPP-STL:vector中的size和capacity
在vector中与size()和capacity() 相对应的有两个函数: resize(size_type)和reserve(size_type). Size指目前容器中实际有多少元素,对应的res ...
- 虚拟机设置NAT
需要开启虚拟机网络相关服务, 安装虚拟网卡, 还有必须安装 VMware Tools VMware虚拟机下实现NAT方式上网1. 把你的虚拟网卡VMnet8设置为自动获得IP.自动获得DNS服务器,启 ...
- cocos2dx 3.x for lua "异步加载"实现过程
在lua中,cocos2dx 建立的栈只能被一个线程(主线程)访问,如果在c++建立子线程,然后通过c++调用lua回调函数实现异步加载就会报错. 如果试图通过c++子线程直接实现加载资源,返回一个布 ...
- 【转】vxworks的default boot line说明
boot程序的主要功能是引导vxworks 内核,所以boot程序需要知道vxworks的内核存放在何处,通过什么手段去获取.在vxworks缺省的boot程序里有一条内建的default boot ...
- RAID阵列搭建
RAID0 2个或2个以上磁盘,称为条带卷,无容错,可提高读写效率,其中一个磁盘损坏,所有文件不可读磁盘大小尽量统一,或者以最小的空间为标准,可用空间=N*min RAID1 2个或2个磁盘以上,称为 ...
- k8s Pod的自动水平伸缩(HPA)
我们知道,当访问量或资源需求过高时,使用:kubectl scale命令可以实现对pod的快速伸缩功能 但是我们平时工作中我们并不能提前预知访问量有多少,资源需求多少. 这就很麻烦了,总不能为了需求总 ...