Cod sursa(job #1569321)

Utilizator usermeBogdan Cretu userme Data 15 ianuarie 2016 12:35:19
Problema Lowest Common Ancestor Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 1.49 kb
#include <stdio.h>
#include <assert.h>
#include <vector>
#include <queue>

using std::vector;
using std::queue;

const int MAX_N = 100000;
const int LOG_MAX_N = 17;

int N, M;

vector<int> sons[1 + MAX_N];

int depth[1 + MAX_N];
int father[1 + LOG_MAX_N][1 + MAX_N];

queue<int> bfsQ;

void climb(int &node, int level) {
  int i;
  for (i = 0; level > 0; i++, level >>= 1) {
    if ((level & 1) > 0) {
      node = father[i][node];
    }
  }
}

int main() {
  int i, j;
//  freopen("lca.in", "r", stdin);
//  freopen("lca.out", "w", stdout);
  scanf("%d %d", &N, &M);
  for (i = 2; i <= N; i++) {
    scanf("%d", &father[0][i]);
    sons[father[0][i]].push_back(i);
  }
  for (i = 1; i <= LOG_MAX_N; i++) {
    for (j = 1; j <= N; j++) {
      father[i][j] = father[i - 1][father[i - 1][j]];
    }
  }
  bfsQ.push(1);
  depth[1] = 1;
  while (!bfsQ.empty()) {
    int node = bfsQ.front();
    bfsQ.pop();
    for(int son : sons[node]) {
      bfsQ.push(son);
      depth[son] = depth[node] + 1;
    }
  }

  for (i = 1; i <= M; i++) {
    int a, b;
    int lca;
    scanf("%d %d", &a, &b);

    int dif = depth[a] - depth[b];
    if (dif < 0) {
      climb(b, -dif);
    } else {
      climb(a, dif);
    }
    assert(depth[a] == depth[b]);

    if (a == b) {
      lca = a;
    } else {
      for(j = LOG_MAX_N; j >= 0; j--) {
        if (father[j][a] != father[j][b]) {
          a = father[j][a];
          b = father[j][b];
        }
      }
      lca = father[0][a];
    }

    printf("%d\n", lca);
  }
  return 0;
}