Lowest Common Ancestor
概要
2つの頂点について,それぞれの共通祖先のうち最も深いものを求める.
計算量
前計算$O(N\log N)$,クエリ$O(\log N)$
ソースコード
struct Edge{
int to;
};
using Graph = vector<vector<Edge>>;
struct LA{
Graph G;
vector<vector<int>> ancestor;
//ancestor[i][j]:=頂点iの2^j個親
vector<int> depth;//深さ
int N;
int root = 0;
const int maxDepth = 25;
LA(int _N){
this-> N = _N;
init();
}
void init(){
G.resize(N);
depth.resize(N);
ancestor.resize(N);
for(int i=0;i<N;i++){
ancestor[i].resize(maxDepth);
}
}
void build(){
ancestor[root][0] = root;
bfs(root,root,0);
for(int i=1;i<maxDepth;i++){
for(int j=0;j<N;j++){
ancestor[j][i] = ancestor[ancestor[j][i-1]][i-1];
}
}
}
void bfs(int n,int pre,int d){
depth[n] = d;
ancestor[n][0] = pre;
for(auto&E:G[n]){
if(E.to==pre)continue;
bfs(E.to,n,d+1);
}
}
//頂点nのs個先の祖先
int anc(int n,int s){
for(int i=0;i<maxDepth;i++){
if(s&(1<<i)){
n = ancestor[n][i];
}
}
return n;
}
//頂点nの深さs(root=0)の祖先
int levelAnc(int n,int s){
return anc(n,depth[n]-s);
}
//頂点a,bの共通最近祖先
int lca(int a,int b){
if(depth[a]<depth[b])swap(a,b);
a = levelAnc(a,depth[b]);//同じ深さにする
if(a==b)return a;
for(int k=maxDepth-1;k>=0;k--){
if(ancestor[a][k]!=ancestor[b][k]){
a = ancestor[a][k];
b = ancestor[b][k];
}
}
return ancestor[a][0];
}
};