LCA
2016.1.28
LCA,就是最近公共祖先,这里介绍倍增的算法。
首先我们要预处理,设f[i][j]为编号为i的节点的2j级祖先,所谓2j级祖先,就是从i节点开始往树的上层数2j个节点。如下图所示
编号是乱编的。。。
节点11的20级祖先就是他爹10号节点,节点11的21级祖先就是8号节点,节点11的22级祖先就是6号节点。
这样我们就有递归式:f[i][j]=f[ f[i][j-1] ][ j-1 ],i号节点的2j级祖先就是i号节点的2j-1级祖先的2j-1级祖先。
这件事情我们可以通过从根节点进行一次dfs来完成,在递归之前处理当前结点的祖先即可。
代码如下:
void LCA(int x)
{
vis[x]=;
for(int i=;(<<i)<=dep[x];i++)
{
int c=f[x][i-];//c为x的2^i-1级祖先
f[x][i]=f[c][i-];//f[x][i]赋值为c的2^i-1级祖先
}
for(int i=final[x];i;i=last[i])
{
if(!vis[to[i]])
{
dep[to[i]]=dep[x]+;//更新深度
f[to[i]][]=x;//更新该边到达节点的2^0级祖先
LCA(to[i]);
}
}
}
然后,我们对于询问的节点a和b的最近公共祖先,开始倍增。具体操作如下:(假设在11号和3号节点各站了一个小人a和b)
1、让深度较大的节点(假设是上图11号节点)上的小人沿着边一直向上层跳到和深度较小的节点(假设是上图3号节点)同一深度。(也就是a跳到8号节点)
2、a和b同时开始倍增,如果倍增之后两人所在位置不同,即执行倍增,否则,减小倍增的倍数(假设倍增2k后发现两人在同一位置了,则尝试倍增2k-1)。
3、重复执行操作2,直到无法继续执行。
4、现在,a一定6号节点,b一定在18号节点。换句话说,a和b一定在他俩lca的下一层。
5、a和b往上跳一层便是他俩的lca了
这段操作并不好理解,对着代码看就好了:
int query(int a,int b)
{
if(dep[a]<dep[b]) swap(a,b);
for(int i = maxlog ; i >= ; i-- ) //2^maxlog是这棵树的最大可能深度,从大级别往小级别倍增,直到a跳到与b同深度
if(dep[a]-(<<i)>=dep[b])
a=f[a][i];
if(a==b) return b;//注意特判,b可能就是他俩的lca
for(int i = maxlog ; i >= ; i-- ) //a和b同时开始往上倍增
if(dep[a] > (<<i) && f[a][i] != f[b][i])
{
a=f[a][i];
b=f[b][i];
}
//此时a和b的上一层就是lca
return f[a][];
}
然后再来看题:NOIP201307货车运输
LCA的更多相关文章
- BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 1280 MBSubmit: 3127 Solved: 795[Submit][Status][Discu ...
- BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2050 Solved: 817[Submit][Status ...
- [bzoj3123][sdoi2013森林] (树上主席树+lca+并查集启发式合并+暴力重构森林)
Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...
- [bzoj2588][count on a tree] (主席树+lca)
Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...
- [板子]倍增LCA
倍增LCA板子,没有压行,可读性应该还可以.转载请随意. #include <cstdio> #include <cstring> #include <algorithm ...
- poj3417 LCA + 树形dp
Network Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4478 Accepted: 1292 Descripti ...
- [bzoj3626][LNOI2014]LCA
Description 给出一个$n$个节点的有根树(编号为$0$到$n-1$,根节点为$0$). 一个点的深度定义为这个节点到根的距离$+1$. 设$dep[i]$表示点$i$的深度,$lca(i, ...
- (RMQ版)LCA注意要点
inline int lca(int x,int y){ if(x>y) swap(x,y); ]][x]]<h[rmq[log[y-x+]][y-near[y-x+]+]])? rmq[ ...
- bzoj3631: [JLOI2014]松鼠的新家(LCA+差分)
题目大意:一棵树,以一定顺序走完n个点,求每个点经过多少遍 可以树链剖分,也可以直接在树上做差分序列的标记 后者打起来更舒适一点.. 具体实现: 先求x,y的lca,且dep[x]<dep[y] ...
- 在线倍增法求LCA专题
1.cojs 186. [USACO Oct08] 牧场旅行 ★★ 输入文件:pwalk.in 输出文件:pwalk.out 简单对比时间限制:1 s 内存限制:128 MB n个被自 ...
随机推荐
- JDBC删除表数据
delete 必须使用where 条件指定删除哪一行数据.通常用具有唯一性的主键进行标示. package qddx.JDBC; import java.sql.*; public class Del ...
- 开始写Effective系列总结一些前端的心得
确实是没有时间整理以及总结和发表自己的感慨.难得中秋银行的事情搞完了自己清闲3天,是时候总结一下从大公司做.NET PC 端网站的开发到现在做移动互联网的银行及政府微信公众号的开发的感触.当时自己的选 ...
- CocoaPods报错:The dependency `Alamofire ` is not used in any concrete target
看到这个错误提示,首先看看自己的版本是不是 OS X EI Capitan,也就是10.10以后的版本,因为这个版本是比较新的版本,网络上找的那些安装cocoapod命令其实有些过时了,特别是创建po ...
- S3C2416 看门狗
原理:看门狗自己有个硬件计数器,看门狗开启后,计数器就开始计数,当计数为0时触发,触发事件有两个:系统复位和中断,可设置屏蔽. 在计数器计数到0之前,程序可以重新设置计数器中的数值,称之喟狗.计数器的 ...
- Atom安装activate-power-mode插件(震动炫酷)
1.下载安装Atom,地址:https://atom.io/ 2.下载安装activate-power-mode插件,地址:https://github.com/JoelBesada/activate ...
- golang开发环境(2016.9.16)
一.windows下安装 1.下载go1.7.3.windows-amd64.msi,建议默认安装到‘C:\Go\’ 2.环境变量 变量 值 说明 Path C:\Go\bin 安装程序默认会设置,如 ...
- Nginx和Apache配置日志格式记录Cookie
记录Cookie有什么用? 有时候我们需要通过web服务器的访问日志来统计UV(独立访客),并据此分析用户的行为.而UV是依据cookie数据得出的统计.UV相对于IP的好处是:IP是一个反映网络虚拟 ...
- OpenRefine 数据清洗工具
OpenRefine(官方网站:http://openrefine.org/).它能自动对数据内容进行修正与整理.OpenRefine可以实现数据排序.自动查找重复条目并完成数据记录.OpenRefi ...
- 关于eclipse保存代码很慢,提示the user operation is waiting的问题
关于eclipse保存代码很慢,提示the user operation is waiting的问题 首先 去掉 project - build Automaticlly 然后 project-> ...
- Squid代理服务器
缓存代理概述:做为应用层的代理服务软件,squid主要提供缓存加速,应用层过滤控制的功能. 1.代理的工作机制 当客户机通过代理来请求web页面时,指定的代理服务器会先检查自己的缓存,如果缓存中已经有 ...