博客
关于我
【LCT】P2147 [SDOI2008]洞穴勘测
阅读量:293 次
发布时间:2019-03-03

本文共 3125 字,大约阅读时间需要 10 分钟。

LCT(链接集合树)是一种高效的数据结构,广泛应用于处理各种树状结构的操作问题。以下是基于LCT的实现代码解析与应用示例。

代码结构分析:

  • 数据结构定义

    • 使用二叉树结构表示节点,每个节点包含父指针、左右子树指针以及逆序标记。
    • 树的大小限制为maxn,每个节点初始化时父指针、左右子树指针以及逆序标记都初始化为0。
  • 操作函数

    • isroot:判断一个节点是否为根节点。
    • rev:交换子树方向,并翻转逆序标记。
    • pushdown:将当前节点的子树操作下放到子节点。
    • rotate:旋转节点,使其成为新的根节点。
    • splay:通过旋转操作使树深度减少,提高操作效率。
    • access:通过路径压缩找到目标节点。
    • makeroot:将某个节点设置为根节点,并进行逆序调整。
    • findroot:找到当前树的根节点。
    • link:将两个树连接,形成新的树结构。
    • cut:将两个树分开,确保无环。
  • 代码应用示例:

    #include 
    using namespace std;const int maxn = 2e5;int n, m;struct LCT { struct node { int fa, ch[2], rev; node() { fa = ch[0] = ch[1] = rev = 0; } } tree[maxn]; int top, res[maxn]; #define ls(x) tree[x].ch[0] #define rs(x) tree[x].ch[1] int isroot(int x) { return tree[x].fa && (ls(tree[x].fa) == x || rs(tree[x].fa) == x); } void rev(int x) { swap(ls(x), rs(x)); tree[x].rev ^= 1; } void pushdown(int x) { if (!tree[x].rev) return; if (ls(x)) rev(ls(x)); if (rs(x)) rev(rs(x)); tree[x].rev ^= 1; } void rotate(int x) { int y = tree[x].fa, z = tree[y].fa; int k = (x == ls(tree[x].fa)), w = tree[x].ch[k]; if (isroot(y)) tree[z].ch[y == rs(tree[y].fa)] = x; tree[x].ch[k] = y; tree[y].ch[!k] = w; tree[y].fa = x; tree[x].fa = z; if (w) tree[w].fa = y; } void splay(int x) { int tmp = x; res[top = 1] = tmp; while (isroot(tmp)) { res[++top] = tree[tmp].fa; tmp = tree[tmp].fa; } while (top) { pushdown(res[top]); top--; } while (isroot(x)) { if (isroot(tree[x].fa)) { int k = (x == rs(tree[x].fa)) ^ (tree[x].fa == rs(tree[tree[x].fa].fa)); rotate(k ? tree[x].fa : x); } rotate(x); } } void access(int x) { for (int y = 0; x; x = tree[x].fa) { splay(x); rs(x) = y; } } void makeroot(int x) { access(x); splay(x); rev(x); } int findroot(int x) { access(x); splay(x); while (ls(x)) { pushdown(x); x = ls(x); pushdown(x); } return x; } void link(int x, int y) { if (findroot(x) == findroot(y)) return; makeroot(x); tree[x].fa = y; } void cut(int x, int y) { makeroot(x); access(y); splay(y); if (ls(y) == x) { tree[x].fa = ls(y) = 0; } }} LCT;int main() { freopen("a.in", "r", stdin); freopen("a.out", "w", stdout); scanf("%d%d", &n, &m); char op[20]; int x, y; for (int i = 1; i <= m; ++i) { scanf("%s", op); scanf("%d%d", &x, &y); if (op[0] == 'C') { LCT.link(x, y); } else if (op[0] == 'D') { LCT.cut(x, y); } else if (op[0] == 'Q') { if (LCT.findroot(x) == LCT.findroot(y)) { printf("Yes\n"); } else { printf("No\n"); } } } return 0;}

    以上代码实现了一个高效的LCT结构,支持常规的树操作,如连接、切割以及根节点查询等功能。通过路径压缩和旋转操作,LCT显著提升了树操作的效率,使得复杂度接近线性。

    转载地址:http://idwm.baihongyu.com/

    你可能感兴趣的文章
    Python Selenium模块详解
    查看>>
    Python selenium爬取影评生成词云图
    查看>>
    python selenium自动化测试报告
    查看>>
    Python selenium自动化测试框架实战 —— 登录测试案例
    查看>>
    Python Selenium设计模式 —— POM
    查看>>
    Python Serial:如何使用 read 或 readline 函数一次读取多个字符
    查看>>
    Python set([]) 如何检查两个对象是否相等?一个对象需要定义哪些方法来自定义它?
    查看>>
    Python setup.py:数据文件无法复制目录:不存在或不是常规文件
    查看>>
    Python setuptools sdist:仅安装版本化文件
    查看>>
    Python Shell下使用matplotlib
    查看>>
    Python Slice How-to,我知道Python Slice,但我怎么才能使用内置的Slice对象呢?
    查看>>
    python socket分包发送数据
    查看>>
    python socket模块_Python socket模块实现TCP服务端客户端
    查看>>
    Python SOCKS5代理客户端HTTPS
    查看>>
    Python Soc网络分析:通过使用函数迭代列表来计算机会网络
    查看>>
    Python SQL和NoSQL数据库操作实战
    查看>>
    python stdout flush_sys.stdout.flush()方法的用法
    查看>>
    python string 运算
    查看>>
    Python str与bytes之间的转换
    查看>>
    Python subprocess ffmpeg
    查看>>