一天天的为了啥。|

lgh_2009

园龄:1年粉丝:1关注:0

最近公共祖先 学习笔记

概念

一棵有根树,求两个点的最近公共祖先。

方法

1. 倍增法:O(n)O(logn)

int lca(int x,int y) {
if(dep[x]<dep[y]) swap(x,y);
while(dep[x]>dep[y]) x=fa[x][__lg(dep[x]-dep[y])-1];
if(x==y) return x;
for(int k=__lg(dep[x])-1; ~k; k--)
if(fa[x][k]!=fa[y][k]) x=fa[x][k],y=fa[y][k];
return fa[x][0];
}

2. dfs 序求 lca:O(nlogn)O(1)

int get(int x,int y) {return dfn[x]<dfn[y]?x:y;}
void dfs(int x,int fa) {
st[dfn[x]=++cnt][0]=fa;
st[1][1]=fa;
for(auto y:e[x]) if(y!=fa) dfs(y,x);
}
void build_st() {
int k=__lg(n);
for(int i=1; i<=k; i++)
for(int j=1; j+(1<<i)-1<=n; j++)
st[j][i]=get(st[j][i-1],st[j+(1<<(i-1))][i-1]);
}
int lca(int x,int y) {
if(x==y) return x;
if((x=dfn[x])>(y=dfn[y])) swap(x,y);
int k=__lg(y-x++);
return get(st[x][k],st[y-(1<<k)+1][k]);
}

3. 树剖求 lca:O(n)O(logn)

int lca(int x,int y) {
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;
}

本文作者:lgh_2009

本文链接:https://www.cnblogs.com/lgh-blog/p/18133844

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   lgh_2009  阅读(7)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起