倍增这种东西,听起来挺高级,其实功能还没有线段树强大。线段树支持修改、查询,而倍增却不能支持修改,但是代码比线段树简单得多,而且当倍增这种思想被应用到树上时,它的价值就跟坐火箭一样,噌噌噌地往上涨。

关于倍增思想:

倍增的思想很简单:通过区间[1,2i-1]与[1+2i-1,2i(2i-1+2i-1)]求出区间[1,2i]。

所以它可以用于区间求最值,求和。而到了树上之后,就变成了,求它往上任意次的祖先。

而倍增求LCA,就是用到了倍增这个功能。

倍增求LCA算法思路:

f[i,j],表示结点i,向上跳2j次跳到的点为f[i,j]。

显然f[i,0]中存的是i结点的父亲。

而f[i,j]=f[f[i,j-1],j-1],所以我们可以很简单的就求出f数组。

那么我们应该如何用它来求LCA呢?

两个结点a,b。(假设a的深度小于b)

首先我们让两个结点跳到同一深度(那个深度小跳到哪儿),这个过程可以用倍增来加速:从大到小枚举i,判断b往上跳2i是否会超过a,如果会,就不跳,不会,就跳。

这个为什么对于每个2i最多只会跳一次呢?

——你跳两次2i,我不会直接跳一次2i+1吗,动动脚趾都知道了嘛!

当它们处于同一高度时会产生两种情况:1、a=b,说明a本来就是b的祖先。2、a<>b,这个时候我们也是从大到小枚举i,判断a和b两者都向上跳2i次(假设此时在结点C,D)会不会重合,若重合,说明它们的LCA在C的下面,不跳,若不重合则说明LCA在C、D的上面,那么就让a跳到C,b跳到D。最后再把a(或b)往上跳1次,就是LCA了!

那么为什么最后要向上跳一次呢?

——如果在某时刻我们往上跳2i次就能跳到LCA的话,那么C就会与D重合,所以并不会跳上去,而是会往上跳(2i-1+2i-2+...+21+20)次。所以我们在最后取其父亲就能够得到LCA了。

代码:

var
f:array[0..100000,0..20]of longint;
next,dist,vet:array[0..200000]of longint;
x,y,z,a,b,i,j,k,n,m,tot,ans,sum:longint;
procedure add(x,y,z:longint);
begin
inc(tot);
next[tot]:=head[x];
vet[tot]:=y;
head[x]:=tot;
dist[tot]:=z;
end;
procedure dfs(u,dep:longint);
var
i,v:longint;
begin
depth[u]:=dep; vis[u]:=true;
for i:=1 to 20 do
f[u,i]:=f[f[u,i-1],i-1];
i:=head[u];
while i<>0 do
begin
v:=vet[i];
if not vis[v] then
begin
f[v,0]:=u;
dfs(v,dep+1);
end;
i:=next[i];
end;
end;
function lca(a,b:longint):longint;
var
i,t:longint;
begin
if depth[a]>depth[b] then begin t:=a; a:=b; b:=t; end;
for i:=20 downto 0 do
if depth[f[b,i]]>=depth[a] then b:=f[b,i];
if a=b then exit(a);
for i:=20 downto 0 do
if f[a,i]<>f[b,i] then
begin
a:=f[a,i]; b:=f[b,i];
end;
exit(f[a,0]);
end;
begin
read(n);
for i:=1 to n-1 do
begin
read(x,y,z);
add(x,y,z); add(y,x,z);
end;
dfs(1,1);
read(m);
for i:=1 to m do
begin
read(x,y);
writeln(lca(x,y));
end;
end.

[学习笔记] 树上倍增求LCA的更多相关文章

  1. 树上倍增求LCA(最近公共祖先)

    前几天做faebdc学长出的模拟题,第三题最后要倍增来优化,在学长的讲解下,尝试的学习和编了一下倍增求LCA(我能说我其他方法也大会吗?..) 倍增求LCA: father[i][j]表示节点i往上跳 ...

  2. [算法]树上倍增求LCA

    LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4 ...

  3. 树上倍增求LCA及例题

    先瞎扯几句 树上倍增的经典应用是求两个节点的LCA 当然它的作用不仅限于求LCA,还可以维护节点的很多信息 求LCA的方法除了倍增之外,还有树链剖分.离线tarjan ,这两种日后再讲(众人:其实是你 ...

  4. Codeforces 609E (Kruskal求最小生成树+树上倍增求LCA)

    题面 传送门 题目大意: 给定一个无向连通带权图G,对于每条边(u,v,w)" role="presentation" style="position: rel ...

  5. 树上倍增求LCA详解

    LCA(least common ancestors)最近公共祖先 指的就是对于一棵有根树,若结点z既是x的祖先,也是y的祖先(不要告诉我你不知道什么是祖先),那么z就是结点x和y的最近公共祖先. 定 ...

  6. [luogu3379]最近公共祖先(树上倍增求LCA)

    题意:求最近公共祖先. 解题关键:三种方法,1.st表 2.倍增法 3.tarjan 此次使用倍增模板(最好采用第一种,第二种纯粹是习惯) #include<cstdio> #includ ...

  7. CF 519E(树上倍增求lca)

    传送门:A and B and Lecture Rooms 题意:给定一棵树,每次询问到达点u,v距离相等的点有多少个. 分析:按情况考虑: 1.abs(deep[u]-deep[v])%2==1时, ...

  8. 树上倍增求LCA

    大概思想就是,节点$i$的第$2^{j}$个父节点是他第$2^{j-1}$个父亲的第$2^{j-1}$个父亲 然后可以$O(nlogn)$时间内解决…… 没了? //fa[i][j]表示i的第2^j个 ...

  9. 倍增求LCA学习笔记(洛谷 P3379 【模板】最近公共祖先(LCA))

    倍增求\(LCA\) 倍增基础 从字面意思理解,倍增就是"成倍增长". 一般地,此处的增长并非线性地翻倍,而是在预处理时处理长度为\(2^n(n\in \mathbb{N}^+)\ ...

随机推荐

  1. Mybatis源码学习第七天(插件源码分析)

    为了不把开发和源码分析混淆,决定分开写; 接下来分析一下插件的源码,说道这里老套路先说一个设计模式,他就是责任链模式 责任链模式:就是把一件工作分别经过链上的各个节点,让这些节点依次处理这个工作,和装 ...

  2. leetcode刷题-69x的平方根

    题目 实现 int sqrt(int x) 函数. 计算并返回 x 的平方根,其中 x 是非负整数. 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去. 示例 1: 输入: 4输出: 2 思 ...

  3. Tcahce Stashing Unlink Attack

    今年校赛有点可惜,最后两道质量不错的pwn每做出来,总的来说还是我太菜了,希望下次校赛能AK pwn题.不过这次校赛也没有白打,还是有学到新的东西的.在这里感谢出题的学长. glibc-2.29以后u ...

  4. Dos拒绝服务攻击DNS、SNMP、NTP放大攻击和slowhttptest攻击工具(三)

    DNS放大攻击产生大流量的攻击方式 udpDNS放大效果-查询请求流量小,但响应流量可能非常巨大-dig ANY baidu.com @1.1.1.1 //向1.1.1.1的服务器查询域名解析,流量放 ...

  5. xss原理解析

    xss->跨站脚本攻击 xss是指攻击者在网页中嵌入客户端脚本.通常是指javascript编写的一个危险代码,当用户使用浏览器浏览网页时,脚本就会在用户的浏览器上执行,从而达到攻击者的目的. ...

  6. [LeetCode]287. 寻找重复数(二分)

    题目 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 1: 输入: [ ...

  7. Gradle系列之Android Gradle插件

    原文发于微信公众号 jzman-blog,欢迎关注交流. 通过前面几篇文章学习了 Gradle 基础知识以及 Gradle 插件相关的知识,关于 Gradle 及其插件相关知识请先阅读下面几篇文章: ...

  8. JavaGuide易错点总结

    基础知识易错点 1. object.equals("str") 容易报空指针异常,应使用"str".equals(object); 还可以使用JDK7引入的工具 ...

  9. redis之哨兵部署运行日志解读

    转载自http://www.run-debug.com/?p=674 192.168.110.21 主 192.168.110.31 从 #两台服务器都安装redis #下载最新稳定版本:http:/ ...

  10. Java文件操作API功能与Windows DOS命令和Linux Shell 命令类比

    Java文件操作API功能与Windows DOS命令和Linux Shell 命令类比: Unix/Linux (Bash) Windows(MS-DOS) Java 进入目录 cd cd - 创建 ...