lca求树上两点最近的公共祖先。
对于树上两点最近的公共祖先,我们首先能想到的办法,就是暴力,如果深度不相同先调整到相同深度,如果深度相等了,祖先不同的话,就继续向上找,直到找到相同的公共祖先。
但是这样的方法,显然速度太慢,那么我们该怎么寻找两个点最近的公共祖先呢?
我们可以处理一颗树上的所有点将其所有的2的次幂的祖先处理出来,放在一个数组中,寻找两个点共同公共祖先时,首先将两个点深度调到一致,然后我们两个点一起向上找直到找到共同的公共祖先。
代码:
首先预处理深度,公共祖先数组:
void dfs(int pre,int rt)
{
depth[rt]=depth[pre]+1;
fa[rt][0]=pre;
for(int i=1;i<20;i++)
{
fa[rt][i]=fa[fa[rt][i-1]][i-1];
}
for(int i=0;i<edge[rt].size();i++)
{
if(edge[rt][i]!=pre)
dfs(rt,edge[rt][i]);
}
}
之后直接,lca搜索公共祖先即可:
int lca(int x,int y)
{
if(depth[x]<depth[y])
swap(x,y);
for(int i=18;i>=0;i--)
{
if(depth[x]-(1<<i)>=depth[y])
x=fa[x][i];
}
if(x==y)
return x;
for(int i=18;i>=0;i--)
{
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
}
return fa[x][0];
}
lca的简单应用:
找一棵树上两个点最短距离:
我们事先处理过深度数组,那么对于一直的两个点,根据其深度即可求得两个点最短距离:
depth[x]+depth[y]-2*depth[lca(x,y)]即可;
int dis(int x,int y)
{
int lca=LCA(x,y);
if(lca==0)
{
lca=0;
}
return depth[x]+depth[y]-2*depth[lca];
}