Pagini recente » Rating Vlad Cociorva (vladcociorva) | Arhiva de probleme | Cod sursa (job #1177126) | Cod sursa (job #730138) | Cod sursa (job #1572237)
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define Nadejde 100000
#define MAX_LOG 16
typedef struct {
int v, next;
} list;
int N, Q, lim;
int d[Nadejde + 1];
int lg[Nadejde + 2]; // lg[i] este log2(i).
list l[Nadejde + 1]; // lista arcelor din arbore.
int adj[Nadejde + 1]; // capetele listelor de adiacenta.
int father[MAX_LOG + 1][Nadejde + 1]; // father[i][u] este al 2 ^ i - lea tata al nodului "u".
/** Adauga-l pe "v" la lista de adiacenta a nodului "u". **/
void addEdge(int u, int v, int pos) {
l[pos].v = v;
l[pos].next = adj[u];
adj[u] = pos;
}
/** Exploreaza graful, calculand adancimea fiecarui nod. **/
void dfs(int u, int dad) {
int pos;
if (!d[u]) {
d[u] = d[dad] + 1;
for (pos = adj[u]; pos; pos = l[pos].next) {
dfs(l[pos].v, u);
}
}
}
/** Precalculeaza "lg". **/
void log() {
int i;
for (i = 0; i <= MAX_LOG; i++) {
lg[1 << i] = i;
}
for (i = 3; i <= lim; i++) {
if (!lg[i]) {
lg[i] = lg[i - 1];
}
}
}
/** Urca nodul "u" cu "level" nivele. **/
void climb(int *u, int level) {
for (; level; level &= level - 1) {
(*u) = father[lg[level & -level]][*u];
}
}
int main(void) {
int u, v, i, diff, result;
FILE *f = fopen("lca.in", "r");
/* Citirea datelor. */
fscanf(f, "%d %d", &N, &Q);
for (lim = N + 1, u = 2; u <= N; u++) {
fscanf(f, "%d", &father[0][u]);
addEdge(father[0][u], u, u - 1);
}
/* Calcularea solutiei. */
dfs(1, 0);
log();
/* Precalcularea parintilor. */
for (i = 1; i <= lg[lim]; i++) {
for (u = 1; u <= N; u++) {
father[i][u] = father[i - 1][father[i - 1][u]];
}
}
/* Raspunde la intrebari. */
freopen("lca.out", "w", stdout);
while (Q--) {
fscanf(f, "%d %d", &u, &v);
/* Vedem pe cine urcam mai sus in arbore. */
diff = d[u] - d[v];
if (diff < 0) {
climb(&v, -diff);
} else {
climb(&u, diff);
}
/* Calcularea lca-ului. */
if (u == v) {
result = u;
} else {
for (i = lg[d[u]]; i >= 0; i--) {
if (father[i][u] != father[i][v]) {
u = father[i][u];
v = father[i][v];
}
}
result = father[0][u];
}
fprintf(stdout, "%d\n", result);
}
fclose(f);
fclose(stdout);
/// Multumim Doamne!
puts("Doamne ajuta!");
return 0;
}