TheAlgorithms-C-Plus-Plus/Graph/lca.cpp

91 lines
1.8 KiB
C++
Raw Normal View History

2019-10-04 21:35:23 +08:00
#include<bits/stdc++.h>
using namespace std;
// Find the lowest common ancestor using binary lifting in O(nlogn)
// Zero based indexing
// Resource : https://cp-algorithms.com/graph/lca_binary_lifting.html
const int N = 1005;
const int LG = log2(N)+1;
struct lca{
int n;
vector<int> adj[N]; // Graph
int up[LG][N]; // build this table
int level[N]; // get the levels of all of them
lca(int n_) : n(n_){
memset(up,-1,sizeof(up));
memset(level,0,sizeof(level));
for(int i=0; i<n-1; ++i){
int a,b;
cin>>a>>b; a--; b--;
adj[a].push_back(b);
adj[b].push_back(a);
}
level[0] = 0;
dfs(0,-1);
build();
}
void verify(){
for(int i=0; i<n; ++i){
cout<<i<<" : level: "<<level[i]<<endl;
}
cout<<endl;
for(int i=0; i<LG; ++i){
cout<<"Power:"<<i<<": ";
for(int j=0; j<n; ++j){
cout<<up[i][j]<<" ";
}
cout<<endl;
}
}
void build(){
for(int i=1; i<LG; ++i){
for(int j=0; j<n; ++j){
if( up[i-1][j] != -1 ){
up[i][j] = up[i-1][up[i-1][j]];
}
}
}
}
void dfs(int node, int par){
up[0][node] = par;
for( auto i : adj[node] ){
if( i != par ){
level[i] = level[node] + 1;
dfs(i,node);
}
}
}
int query(int u, int v){
u--; v--;
if( level[v] > level[u] ){ swap(u,v); }
// u is at the bottom.
int dist = level[u] - level[v];
// Go up this much distance
for(int i=LG-1; i>=0; --i){
if( dist & ( 1 << i) ){
u = up[i][u];
}
}
if( u == v ){ return u; }
assert(level[u] == level[v]);
for(int i=LG-1; i>=0; --i){
if( up[i][u] != up[i][v] ){
u = up[i][u];
v = up[i][v];
}
}
assert(up[0][u] == up[0][v]);
return up[0][u];
}
};
int main(){
int n; // number of nodes in the tree.
lca l(n); // will take the input in the format given
// n-1 edges of the form
// a b
// Use verify function to see.
}