lca的三种算法【倍增 / RMQ / Tajan】
来源:互联网 发布:电影语言翻译软件 编辑:程序博客网 时间:2024/06/05 05:23
- lca:树上两点的最近公共祖先
倍增算法(在线)
- 利用dfs记录结点深度deep[i],并求出单点祖先:f[i][j]:从结点i向上出发
2j 步的祖先,可推出→
f[i][0] = fa[i], f[i][j] = f[f[i][j - 1]][j - 1] - 求两点x,y的lca,不妨令deep[x] >= deep[y],x先爬deep[x]-deep[y]步使得x和y的deep相同;若此时x == y,则x就是最近公共祖先;否则x和y同时爬一些步数后,若到达的点相同,则找到公共祖先,第一个这样的点,就是最近公共祖先。
- 代码:
inline void dfs(int u, int fa){ deep[u] = deep[fa] + 1; f[u][0] = fa; for(int i = 1; i <= 20 && f[u][i - 1] > 0; ++ i) f[u][i] = f[f[u][i - 1]][i - 1]; for(int i = head[u]; i; i = e[i].next) if (e[i].to != fa) dfs(e[i].to, u);}inline int lca(int x, int y){ if (deep[x] < deep[y]) swap(x, y); for(int i = 20; i >= 0; -- i) if (deep[f[x][i]] >= deep[y]) x = f[x][i]; if (x == y) return x; for(int i = 20; i >= 0; -- i) if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i]; return f[x][0];}
- 时间复杂度O(n * log n + q * log n)
RMQ算法(在线)
- dfs并用数组a[0]按时间戳递增记录访问与回溯的结点,用a[1]记录a[0]中结点的深度,并用fir数组标记每一个点在a[0]中第一次出现的时间。
如:【手动画图莫嫌弃QAQ
对于上图中的树,
a[0] = {1, 2, 4, 2, 5, 6, 5, 7, 5, 2, 1, 3, 8, 3, 1};
a[1] = {0, 1, 2, 1, 2, 3, 2, 3, 2, 1, 0, 1, 2, 1, 0};
fir = {1, 2, 12, 3, 5, 6, 8, 13}; - 经过推敲发现,对于两个点x,y的lca为a[1]中(fir[x], fir[y])的最小值所对应a[0]的点,可用RMQ快速查询。
- 代码略去。因与倍增同为在线,我较少使用【但貌似效率较高。推荐一版代码。
Tajan算法(离线)
- Tarjan算法基于从根节点开始DFS时,在刚刚好访问完两个节点时,这两个节点的LCA必定没有在DFS中回溯。
- 当访问完x的每棵子树时,用并查集把这些子树记为与x同集。
- 可发现当dfs访问到v时,u以访问,lca(u, v) = find(v)。【建议手模一下】
- 代码:
inline int find(int x){ return p[x] == x ? x : p[x] = find(p[x]);}inline void dfs(int u, int fa){ vi[u] = true; for(int i = head[u]; i; i = e[i].next) if (e[i].to != fa) { int v = e[i].to; dfs(v, u); p[v] = u; } for(int i = qh[u]; i; i = q[i].next) if (vi[q[i].to]) ans[q[i].id] = find(q[i].to);}
- 时间复杂度:O(n + q)
答案便于记录时,个人感觉tajan好用,简短而快速。
阅读全文
0 0
- lca的三种算法【倍增 / RMQ / Tajan】
- LCA三种算法学习(离线算法tarjan+在线算法转rmq+在线倍增)例题poj1330、1470;hdu4547、2874
- LCA-RMQ倍增算法【codevs.1036
- LCA的倍增算法
- 倍增&RMQ&LCA
- 文章标题 RMQ转LCA算法、基于倍增的方法求LACA
- 三种LCA算法(一):Doubly算法(倍增算法)
- LCA倍增算法(模板)
- lca倍增算法
- lca倍增算法模板
- 倍增算法(LCA)
- lca倍增算法
- RMQ算法以及LCA的ST算法。
- LCA求法--Tarjan与倍增与RMQ
- 倍增(RMQ与LCA)模板
- RMQ与LCA的算法总结
- 最近公共祖先(LCA)算法实现过程 【Tarjan离线+倍增在线+RMQ】
- LCA与RMQ算法
- 谈谈利用JavaScript结合相对单位rem实现自适应布局的简单而实用的方法,亲用有效。
- RxJava操作符
- 用construct 2制作跳跃游戏
- 【ShaderForge】自发光漫反射小练习
- 深入Java集合学习系列:ArrayList的实现原理
- lca的三种算法【倍增 / RMQ / Tajan】
- Linux网络编程( epoll函数的使用) 多路IO 高并发服务器
- ORB-SLAM(二)性能
- 20171101
- Cookie,Session和Token机制和区别.
- 【多线程】pthreads-win32静态库动态库编译方法以及demo示例
- 设计模式---工厂方法
- Acm6-树的遍历
- 移植RT-THREAD+LUA到STM32F4