树上倍增求LCA
树上倍增求LCA
先跑一遍dfs,知道每个结点的父结点是谁,记录在root[x][0],“x”是当前结点,“root[x][0]”是x结点向上一步得到的点(也称为父结点)。
我们可以维护出来每个结点向上2k步会走到哪个结点。如果已经超出树的范围令root[x][k]=0
预处理一下LOG()
inline void Pre()
{
for(int i=0,j=0,nex=2;i<=maxN;i++)
{ if(i==nex) {nex<<=1;j++}
LOG[i]=j;
}
}
深搜索一下
void dfs(int u,int fa)
{
root[u][0]=fa;
deep[u]=deep[fa]+1;
for (int i=0;(1<<(i+1))<N;i++)
root[u][i+1]=root[root[u][i]][i];
for (int i=head[u],v;~i;i=edge[i].nex)
{
v=edge[i].to;
if(v==fa) continue;
dfs(v,u);
}
}
求LCA
inline int _Lca(int x,int y)
{
if (deep[x]<deep[y]) swap(x,y);
int det=deep[x]-deep[y];
for(int i=LOG[det];i>=0;i--)
if((det>>i)&1) x=root[x][i];
if(x==y) return x;
for(int i=LOG[N];i>=0;i--)
{
if (root[x][i]^root[y][i])
{ x=root[x][i],y=root[y][i];}
}
return root[x][0];
}