Do BFS first for depth info wrt a random node.
void bfs(vector& adj,vector& par,VII& depth,int& n)
{
//arbitrarily root the tree
VII vis(n,false);
depth[0]=0;
vis[0]=true;
queue q;
q.push(0);
while(!q.empty())
{
int u=q.front();
q.pop();
for(auto it:adj[u])
if(!vis[it])
{
vis[it]=true;
depth[it]=depth[u]+1;
par[0][it]=u;
q.push(it);
}
}
}
Preprocess Step
void preprocess(vector<VII>& par,int& n,int& D)
{
for(int d=0;d<=D;++d)
{
for(int i=0;i<n;++i)
{
int mid=par[d-1][i];
if(mid!=-1)
par[d][i]=par[d-1][mid];
}
}
}
Walk and LCA
int walk(int i,int k,int& D,vector<VII>& par)
{
//To make a node i at depth d
for(int d=0;d<=D && i!=-1;++d)
if((i<<d)&k)i=par[d][i];
return i;
}
int LCA(int a,int b,vector<VII>& par,VII& depth,int &D)
{
if(depth[a]>depth[b])
a=walk(a,depth[a]-depth[b],D,par);
else if(depth[b]>depth[a])
b=walk(b,depth[b]-depth[a],D,par);
if(a==b)
return a;
for(int d=D;d>=0;--d)
{
//to go close faster make big jumps
if(par[d][a]!=par[d][b])
{
a=par[d][a];
b=par[d][b];
}
}
return par[0][a];
}
int D=log2(n);