关于LCA的几点想法
倍增
这是最最最常见的写法了,一个fa[N][logN]的数组直接搞定
时间复杂度也不算太高
预处理 $ O(nlogn) $ 如果你想卡的话,可以卡到 $ O(nlogh) $ h为树的深度
查询 $ O(2*logn) $ 最坏,平均 $ O(logn) $
$ code $
int dfn[N],cnt;
int dep[N],fa[N][21],siz[N];
void dfs_first(int x){
dfn[x]=++cnt;
siz[x]=1;
for(re i=head[x];i;i=nxt[i]){
int y=to[i];
if(y==fa[x][0])continue;
fa[y][0]=x;
for(re i=1;i<=20;i++)fa[y][i]=fa[fa[y][i-1]][i-1];//cout<<fa[y][i]<<endl;
dep[y]=dep[x]+1;
dfs_first(y);
siz[x]+=siz[y];
}
}
int LCA(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(re i=20;i>=0;i--)
if(dep[fa[x][i]]>=dep[y])
x=fa[x][i];
if(x==y)return x;
for(re i=20;i>=0;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
注意::::dep[1]要赋值为1,否则求取LCA时就全是0了
RMQ
这个真是神级算法了
利用RMQ的原理找到LCA
为什么呢? 因为在两个点的之间,最近的公共祖先一定是,这两个点的dfs序中,深度最小的那个
这样问题就转化成了在区间上求最小值,也就是RMQ问题
最最最恐怖的是他的时间复杂度
预处理与倍增相同 $ O(nlogn) $ 不能卡到h
但是查询快爆了 $ O(1) $
$ code $
int dfn[N],cnt;
int dep[N],fa[N];
int st[N][21],lg2[N];
void dfs_first(int x){
dfn[x]=++cnt;
st[cnt][0]=x;
for(re i=head[x];i;i=nxt[i]){
int y=to[i];
if(y==fa[x])continue;
fa[y]=x;
dep[y]=dep[x]+1;
dfs_first(y);
}
}
void get_st(){
for(re i=2;i<=n;i++)lg2[i]=lg2[i>>1]+1;
for(re j=1;j<=20;j++){
for(re i=1;i+(1<<j)-1<=n;i++){
int r=i+(1<<j-1);
st[i][j]=dep[st[i][j-1]]<dep[st[r][j-1]]?st[i][j-1]:st[r][j-1];
}
}
}
int LCA(int x,int y){
x=dfn[x];y=dfn[y];
if(x>y)swap(x,y);
int tmp=lg2[y-x+1];
return dep[st[x][tmp]]<dep[st[y-(1<<tmp)+1][tmp]]?st[x][tmp]:st[y-(1<<tmp)+1][tmp];
}
所以这个还是比倍增稍微快一点的
树链剖分
这个更快不信你往下看
就是简单的根据树链剖分的top一直往上跳
我们分析一下复杂度
预处理 $ O(2*n) $ 这个完全没有争议
查询,这个查询总起来是比倍增快一些的
因为一般的题不会给你出一颗满二叉树,所以我们每次向上跳,会远远少于logh
毕竟如果每次节点都在轻链上,高度就是logn,没有争议,比倍增快
除非他卡你,就算卡你,你也是logn,快快快快爆了
所以查询的复杂度是 $ O(logn) $ 但是实际应用时,比这个快多了
$ code $
int dfn[N],cnt,fa[N];
int siz[N],son[N],dep[N],top[N];
void dfs1(int x){
dfn[x]=++cnt;siz[x]=1;son[x]=0;
for(re i=head[x];i;i=nxt[i]){
int y=to[i];
if(y==fa[x])continue;
fa[y]=x;dep[y]=dep[x]+1;
dfs1(y);siz[x]+=siz[y];
if(!son[x]||siz[y]>siz[son[x]])son[x]=y;
}
}
void dfs2(int x,int f){
top[x]=f;
if(son[x])dfs2(son[x],f);
for(re i=head[x];i;i=nxt[i]){
int y=to[i];
if(y==son[x]||y==fa[x])continue;
dfs2(y,y);
}
}
int LCA(int x,int y){
//cout<<x<<" "<<y<<" "<<top[x]<<" "<<top[y]<<endl;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
所以就完事了
所以好像昂还有一个tarjan的离线算法
好像弱爆了,所以我基本不用他
关于LCA的几点想法的更多相关文章
- hdu3087 LCA + 暴力
Network Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Su ...
- 【BZOJ-3712】Fiolki LCA + 倍增 (idea题)
3712: [PA2014]Fiolki Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 303 Solved: 67[Submit][Status] ...
- hihoCoder挑战赛11.题目4 : 高等理论计算机科学(LCA)
clj在某场hihoCoder比赛中的一道题,表示clj的数学题实在6,这道图论貌似还算可以... 题目链接:http://hihocoder.com/problemset/problem/1167 ...
- hdu2874 LCA
题意:现在有 n 个点与 m 条边的无向无环图,但是图不一定完全连通,边有各自的边权,给出多组询问,查询两点之间的路径权值和,或者输出两点不连通. 一开始有最短路的想法,但是由于询问有 1e6 组,做 ...
- HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...
- LCA问题的ST,tarjan离线算法解法
一 ST算法与LCA 介绍 第一次算法笔记这样的东西,以前学算法只是笔上画画写写,理解了下,刷几道题,其实都没深入理解,以后遇到新的算法要把自己的理解想法写下来,方便日后回顾嘛>=< R ...
- CodeForces 916E Jamie and Tree(树链剖分+LCA)
To your surprise, Jamie is the final boss! Ehehehe. Jamie has given you a tree with n vertices, numb ...
- LCA 各种神奇的LCA优化方法
LCA(Least Common Ancestors) 树上问题的一种. 朴素lca很简单啦,我就不多说了,时间复杂度n^2 1.倍增LCA 时间复杂度 nlongn+klogn 其实是一种基于朴素l ...
- FB面经 Prepare: LCA of Deepest Nodes in Binary Tree
给一个 二叉树 , 求最深节点的最小公共父节点 . retrun . 先用 recursive , 很快写出来了, 要求用 iterative . 时间不够了... Recursion: 返回的时候返 ...
随机推荐
- 通过Dapr实现一个简单的基于.net的微服务电商系统(十三)——istio+dapr构建多运行时服务网格之生产环境部署
之前所有的演示都是在docker for windows上进行部署的,没有真正模拟生产环境,今天我们模拟真实环境在公有云上用linux操作如何实现istio+dapr+电商demo的部署. 目录:一. ...
- DOM0和DOM2事件的应用和区别详细对比
1.触发次数 零级事件只能注册一次,如果注册多次,后面的会覆盖前面的 btn.onclick = function () { alert(1) } btn.onclick = function () ...
- ruby基础(四)
ruby基础知识 模块 模块是ruby的特色功能之一.如果说类是事物的实体以及行为,那么模块表现的 就是事物的行为部分,模块和类有以下两点不同: 模块不能拥有实例 模块不能被继承 模块的使用方法 mo ...
- [web] 虚拟机网络设置
三种模式 桥接(Bridged):主机网卡--虚拟网桥--虚拟机网卡,把主机虚拟为交换机,虚拟机ip需与主机设置在同一网段,网关与DNS与主机网卡一致 地址转换(NAT):主机网卡--虚拟NAT设备- ...
- 如何用Python画一个圣诞树呢?
# ./sd.py * *** ***** ******* ********* |[root@bogon shengdan]# vim sd.py[root@bogon shengdan]# cat ...
- [转载]XStar's Libvirt+KVM部署记录 目录
XStar's Libvirt+KVM部署记录 目录 Create: 2013-12-11 Update: 2014-01-03 准备工作 KVM网站 http://sourceforge.net/p ...
- zabbix官方源替换为阿里云的zabbix源,一键脚本。(安装zabbix报错curl#18 - "transfer closed with 2988713 bytes remaining to read":15 ETA Trying other mirro)
最近突然安装zabbix总是报错,比如 (24/27): t1lib-5.1.2-14.el7.x86_64.rpm | 166 kB 00:00:00 zabbix-web-4.4.6-1.el7. ...
- linux基础之用户及用户组管理
本节内容 用户管理 1. 为什么需要用户? 1.linux是一个多用户系统 2.权限管理(权限最小化) 2. 用户相关文件 /etc/passwd -->用户基本信息 /etc/shadow - ...
- linux中级之lvs概念
一.lvs介绍 LVS的英文全称是Linux Virtual Server,即Linux虚拟服务器.它是我们国家的章文嵩博士的一个开源项目.在linux内存2.6中,它已经成为内核的一部分,在此之前的 ...
- 『动善时』JMeter基础 — 24、JMeter中使用“用户参数”实现参数化
目录 1.用户参数组件介绍 2.用户参数界面介绍 3.使用"用户参数"组件实现参数化 (1)测试计划内包含的元件 (2)线程组元件内容 (3)HTTP请求组件内容 (4)用户参数组 ...