SyntaxHighlighter

Sunday 15 April 2018

Find out LCA using binary rising uproach

There are a lot of algorithms to find out LCA (least common ancestor) for two tree nodes.
Below is a code which uses binary rise approach with N*Log(N) complexity and N*Log(N) memory usage.

#define rep(i,lo,hi) for(int i=lo;i<=hi;++i)
#define repr(i,hi,lo) for(int i=hi;i>=lo;--i)
const int MAXN = 1 << 17;
const int MAXB = 29;
typedef int arr[MAXN];
vi G[MAXN];
arr H, Path;
int B[MAXN][MAXB+1];
int N;

// Preprocessing
void BuildB(int u, int path[], int npath) {
 int pos = npath - 1;
 rep(i,0,MAXB) {
  if (pos >= 0) {
   B[u][i] = Path[pos];
   pos -= (1 << i);
  } else {
   B[u][i] = 1; // Root
  }
 }
}

void Visit(int u, int h, int p) {
 BuildB(u, Path, h);
 H[u] = h; // height
 Path[h] = u; // add to path 

 for (int i = 0; i < G[u].size(); ++i) {
  int v = G[u][i];
  if (v == p) continue;
  Visit(v, h + 1, u);
 }
}

void PrepareTree() {
 Visit(1, 0, 0);
}

// LCA Queries
int Upfrom(int u, int d) {
 repr(p,MAXB,0) {
  if (d >= (1 << p)) {
   d -= (1 << p);
   u = B[u][p];
  }
 }
 return u;
}

int LCA(int u, int v) {
 if (H[u] < H[v]) swap(u, v);
 if (H[u] > H[v]) {
  int d = H[u] - H[v];
  u = Upfrom(u, d);
 } 
 if (u == v) return u;
 for (int p = MAXB; p >= 0; p--) {
  if (B[u][p] != B[v][p]) { // move up if can
   u = B[u][p];
   v = B[v][p];
  }
 }
 return B[u][0];
}

No comments:

Post a Comment