Tourists Gym - 101002I LCA——dfs+RMQ在线算法
LCA(Least Common Ancestors),即最近公共祖先,是指这样一个问题:在有根树中,找出某两个结点u和v最近的公共祖先(另一种说法,离树根最远的公共祖先)。
知识需求:1)RMQ的ST算法 2)欧拉序列
1)RMQ的ST算法:
可以参考我的这篇博客:RMQ原理及实现
2)欧拉序列:
所谓欧拉序,就是从根结点出发,按dfs的顺序经过每一个结点最后绕回原点的顺序,比如下面这个例子,欧拉序就是A-B-D-B-E-G-E-B-A-C-F-H-F-C-A

那么欧拉序和rmq与LCA有什么关系呢,首先我们知道RMQ可以方便的在线求出区间最小值,以求上图中DG两点最近公共祖先为例,我们先处理出他的欧拉序,我们记录下每个结点第一次被访问的时间,以及每个时间访问的结点编号与结点深度,这时,我们不难发现,D与G第一次出现的时间之间的区域深度最小值就是这两个点对应的最近公共祖先B的深度,我们修改rmq,让其不再返回最小深度,而是返回区间最小深度对应的下标,这里就是求欧拉序中的访问时间,有了这个时间,加上之前的记录,我们可以直接得出该点的编号,从而求出最近公共祖先。
练习题:题目链接
练习题AC代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <set>
#include <queue>
#include <map> using namespace std; const int MAXN = * ; int rmq[MAXN * ]; //节点深度序列 struct ST {
int mm[MAXN * ];
int dp[MAXN][];
void init(int n) {
mm[] = -;
for(int i = ; i <= n; ++i) {
mm[i] = ((i & (i - )) == ) ? mm[i - ] + : mm[i - ];
dp[i][] = i;
}
for(int j = ; j <= mm[n]; ++j)
for(int i = ; i + ( << j) - <= n; ++i)
dp[i][j] = rmq[dp[i][j - ]] < rmq[dp[i + ( << (j - ))][j - ]] ? dp[i][j - ] : dp[i + ( << (j - ))][j - ];
} int query(int a, int b) {
if(a > b) swap(a, b);
int k = mm[b - a + ];
return rmq[dp[a][k]] <= rmq[dp[b - ( << k) + ][k]] ? dp[a][k] : dp[b - ( << k) + ][k];
}
}; struct Edge{
int to, next;
}; Edge edge[MAXN * ];
int tot, head[MAXN]; int F[MAXN * ];
int P[MAXN];
int cnt;
ST st; void init() {
tot = ;
memset(head, -, sizeof(head));
} void addedge(int u, int v) {
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
} int d[MAXN]; void dfs(int u, int pre, int dep) {
d[u] = dep;
F[++cnt] = u;
rmq[cnt] = dep;
P[u] = cnt;
for(int i = head[u]; i != -; i = edge[i].next) {
int v = edge[i].to;
if(v == pre) continue;
dfs(v, u, dep + );
F[++cnt] = u;
rmq[cnt] = dep;
}
} void LCA_init(int root, int node_num) {
cnt = ;
dfs(root, root, );
st.init( * node_num - );
} int query_lca(int u, int v) {
return F[st.query(P[u], P[v])];
} int main()
{
int T, N, u, v;
scanf("%d", &N);
init();
for(int i = ; i < N; ++i) {
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
LCA_init(, N); long long ans = ;
for(int i = ; i + i <= N; ++i) {
for(int j = i + i; j <= N; j += i) {
ans += d[i] + d[j] + - * d[query_lca(i, j)];
}
}
printf("%lld\n", ans); return ;
}
Tourists Gym - 101002I LCA——dfs+RMQ在线算法的更多相关文章
- POJ 1470 Closest Common Ancestors (LCA, dfs+ST在线算法)
Closest Common Ancestors Time Limit: 2000MS Memory Limit: 10000K Total Submissions: 13370 Accept ...
- POJ 1330 Nearest Common Ancestors (LCA,dfs+ST在线算法)
Nearest Common Ancestors Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 14902 Accept ...
- LCA(最近公共祖先)——dfs+ST 在线算法
一.前人种树 博客:浅谈LCA的在线算法ST表 二.沙场练兵 题目:POJ 1330 Nearest Common Ancestors 题解博客:http://www.cnblogs.com/Miss ...
- POJ - 1330 Nearest Common Ancestors(dfs+ST在线算法|LCA倍增法)
1.输入树中的节点数N,输入树中的N-1条边.最后输入2个点,输出它们的最近公共祖先. 2.裸的最近公共祖先. 3. dfs+ST在线算法: /* LCA(POJ 1330) 在线算法 DFS+ST ...
- POJ 1330 Nearest Common Ancestors (dfs+ST在线算法)
详细讲解见:https://blog.csdn.net/liangzhaoyang1/article/details/52549822 zz:https://www.cnblogs.com/kuang ...
- LCA最近公共祖先 ST+RMQ在线算法
对于一类题目,是一棵树或者森林,有多次查询,求2点间的距离,可以用LCA来解决. 这一类的问题有2中解决方法.第一种就是tarjan的离线算法,还有一中是基于ST算法的在线算法.复杂度都是O( ...
- LCA(倍增在线算法) codevs 2370 小机房的树
codevs 2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点, ...
- ST(RMQ)算法(在线)求LCA
在此之前,我写过另一篇博客,是倍增(在线)求LCA.有兴趣的同学可以去看一看.概念以及各种暴力就不在这里说了,那篇博客已经有介绍了. 不会ST算法的同学点这里 ST(RMQ)算法在线求LCA 这个算法 ...
- [CF 191C]Fools and Roads[LCA Tarjan算法][LCA 与 RMQ问题的转化][LCA ST算法]
参考: 1. 郭华阳 - 算法合集之<RMQ与LCA问题>. 讲得很清楚! 2. http://www.cnblogs.com/lazycal/archive/2012/08/11/263 ...
随机推荐
- windows 用VMware创建linux虚拟机,安装操作系统CentOS7.2
1.按照向导创建虚拟机 以下是安装虚拟机的步骤,没有写的直接下一步 [1]主页-创建新虚拟机 [2]选择 自定义(高级) [3]选择稍后安装操作系统 [4]给虚拟机命名并指定所在位置 [5]给处理器配 ...
- Java函数的传参机制
一 最近的一个项目,里面各种返回void,参数用引用类型,那叫一个熟和多,但是也把我绕糊涂了. 我就打算好好理一理java的传参机制,整理一番 二 很多人一听Java的传参,那一定会脱口而出,java ...
- D. Statistics of Recompressing Videos
D. Statistics of Recompressing Videos time limit per test 3 seconds memory limit per test 256 megaby ...
- Aspose.word组件介绍
阅读目录 1.基本介绍 2.文档对象模型概述 本博客所有文章分类的总目录:http://www.cnblogs.com/asxinyu/p/4288836.html 本博客其他.NET开 ...
- 事务的隔离级别和mysql事务隔离级别修改
A事务做了操作 没有提交 对B事务来说 就等于没做 获取的都是之前的数据 但是 在A事务中查询的话 查到的都是操作之后的数据 没有提交的数据只有自己看得到,并没有update到数据库. 查看InnoD ...
- MySQL存储过程多条修改语句
DROP procedure Sel_Function_ActivityPastDueDELIMITER $$DROP procedure IF EXISTS`shouyi`.`Sel_Functio ...
- 表单和HTML5
1.form表单 <form action="" method=""> </form> action: 规定当提交表单时,向何处发送表单 ...
- 基于JavaMail的Java邮件发送:复杂邮件发送
参考:http://blog.csdn.net/xietansheng/article/details/51722660package com.bfd.ftp.utils;import java.ut ...
- Android RecyclerView使用GridLayoutManager间距设置
使用RecyclerView设置间距,需要重写RecyclerView.ItemDecoration这个类.有如下的效果图需要实现,间距只有中间的格子和底部的格式之间有. Paste_Image. ...
- POJ Charm Bracelet 挑饰品 (常规01背包)
问题:去珠宝店抢饰品,给出饰品种数n,能带走的重量m,以及每种饰品的重量w与价值v.求能带走的最大量. 思路:常规01背包. #include <iostream> using names ...