Cod sursa(job #1796039)

Utilizator stoianmihailStoian Mihail stoianmihail Data 3 noiembrie 2016 01:16:31
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.52 kb
#include <stdio.h>

#define MAX_N 100000

typedef struct {
  int v, next;
} list;

int N, M;
int adj[MAX_N + 1];
list l[MAX_N];

int numPaths;
int d[MAX_N + 1];
int loc[MAX_N + 1];
int count[MAX_N + 1];
int size[MAX_N + 1];
int begin[MAX_N + 1];
int path[MAX_N + 1];
int father[MAX_N + 1];

void addEdge(int u, int v, int pos) {
  l[pos].v = v;
  l[pos].next = adj[u];
  adj[u] = pos;
}

void dfs(int u) {
  int v, pos, son = 0;

  count[u] = 1;
  for (pos = adj[u]; pos; pos = l[pos].next) {
    v = l[pos].v;
    d[v] = d[u] + 1;

    dfs(v);

    count[u] += count[v];
    if (count[v] > count[son]) {
      son = v;
    }
  }
  if (son == 0) {
    path[u] = numPaths++;
  } else {
    path[u] = path[son];
  }
  loc[u] = size[path[u]]++;
}

void hpd() {
  father[1] = 1;
  d[1] = 1;
  dfs(1);

  int u;
  for (u = 1; u <= N; u++) {
    loc[u] = size[path[u]] - loc[u] - 1;
    if (loc[u] == 0) {
      begin[path[u]] = u;
    }
  }
}

int lca(int u, int v) {
  while (path[u] != path[v]) {
    if (d[begin[path[u]]] < d[begin[path[v]]]) {
      v = father[begin[path[v]]];
    } else {
      u = father[begin[path[u]]];
    }
  }
  return loc[u] < loc[v] ? u : v;
}

int main(void) {
  int i, u, v;
  FILE *f = fopen("lca.in", "r");
  freopen("lca.out", "w", stdout);

  fscanf(f, "%d %d", &N, &M);
  for (i = 2; i <= N; i++) {
    fscanf(f, "%d", &father[i]);
    addEdge(father[i], i, i - 1);
  }

  hpd();
  while (M) {
    fscanf(f, "%d %d", &u, &v);
    fprintf(stdout, "%d\n", lca(u, v));
    M--;
  }
  fclose(f);
  fclose(stdout);
  return 0;
}