mirror of
https://hub.njuu.cf/TheAlgorithms/C-Plus-Plus.git
synced 2023-10-11 13:05:55 +08:00
91 lines
1.8 KiB
C++
91 lines
1.8 KiB
C++
|
#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.
|
||
|
}
|