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在线算法的更多相关文章

  1. POJ 1470 Closest Common Ancestors (LCA, dfs+ST在线算法)

    Closest Common Ancestors Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 13370   Accept ...

  2. POJ 1330 Nearest Common Ancestors (LCA,dfs+ST在线算法)

    Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14902   Accept ...

  3. LCA(最近公共祖先)——dfs+ST 在线算法

    一.前人种树 博客:浅谈LCA的在线算法ST表 二.沙场练兵 题目:POJ 1330 Nearest Common Ancestors 题解博客:http://www.cnblogs.com/Miss ...

  4. POJ - 1330 Nearest Common Ancestors(dfs+ST在线算法|LCA倍增法)

    1.输入树中的节点数N,输入树中的N-1条边.最后输入2个点,输出它们的最近公共祖先. 2.裸的最近公共祖先. 3. dfs+ST在线算法: /* LCA(POJ 1330) 在线算法 DFS+ST ...

  5. POJ 1330 Nearest Common Ancestors (dfs+ST在线算法)

    详细讲解见:https://blog.csdn.net/liangzhaoyang1/article/details/52549822 zz:https://www.cnblogs.com/kuang ...

  6. LCA最近公共祖先 ST+RMQ在线算法

    对于一类题目,是一棵树或者森林,有多次查询,求2点间的距离,可以用LCA来解决.     这一类的问题有2中解决方法.第一种就是tarjan的离线算法,还有一中是基于ST算法的在线算法.复杂度都是O( ...

  7. LCA(倍增在线算法) codevs 2370 小机房的树

    codevs 2370 小机房的树 时间限制: 1 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点, ...

  8. ST(RMQ)算法(在线)求LCA

    在此之前,我写过另一篇博客,是倍增(在线)求LCA.有兴趣的同学可以去看一看.概念以及各种暴力就不在这里说了,那篇博客已经有介绍了. 不会ST算法的同学点这里 ST(RMQ)算法在线求LCA 这个算法 ...

  9. [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 ...

随机推荐

  1. spring之控制反转

    IOC (Inversion of Control) 控制反转 我的理解:将创建对象的控制权从代码本身转交给了外部容器(spring容器). 1.将组件对象(业务对象)的控制权从代码本身转移到外部容器 ...

  2. UIScrollView使用stoboard自动布局

    使用stoboard布局 scrollView 是有点麻烦的,首先我们往往约束好一个 scrollView 然后在添加子控件,此时都会报错,原因是, scrollView必须确定滚动范围 然后在使用V ...

  3. Servlet--HttpServlet

    一.Servlet 接口(javax.servlet) 定义:     public interface Servlet      Implemented by: FacesServlet, Gene ...

  4. countUp 动画展示数字变化

    html <p id="countUp" style="font-size:25px;height:25px;background-color:#0aa;" ...

  5. IOS 屏幕尺寸、分辨率、点之间的相互关系

    iOS 设备现有的分辨率如下:iPhone/iPod Touch普通屏                         320像素 x 480像素       iPhone 1.3G.3GS,iPod ...

  6. 本号讯 | 永不消失的协作“空间站”开课;微软推出微软云Azure文档网站

    8月29日,针对企业常面临的“协同办公”困难,开展以“还有这种操作?永不消失的协作'空间站'”为主题的协同办公培训课. 课程内容包含:在Office 365环境中,如何利用Teams与Groups等功 ...

  7. 【虚拟机-网络IP】虚拟机配置静态 IP 以后无法连接的解决办法

    问题描述 将虚拟机内部 IP 地址从动态获取改成静态 IP 以后,远程连接失败. 问题分析 Azure 虚拟机的内部 IP 默认为动态分配, 由 DHCP 服务自动分配, 在虚拟机的生命周期内, 该 ...

  8. WebClient UI和Tomcat的启动器

    WebClient UI 我们在WebClient UI的开发工具里点了Test按钮, 会在浏览器以测试模式打开选中的view.这背后发生了什么事?注意浏览器地址栏的bspwd_cmp_test,这是 ...

  9. UVALive 3026 Period (KMP算法简介)

    kmp的代码很短,但是不太容易理解,还是先说明一下这个算法过程吧. 朴素的字符串匹配大家都懂,但是效率不高,原因在哪里? 匹配过程没有充分利用已经匹配好的模版的信息,比如说, i是文本串当前字符的下标 ...

  10. 生成gt数据出问题

    使用cout打印uchar类型数据时,打印出来是其相应的ascii码