Pagini recente » Cod sursa (job #1019148) | Cod sursa (job #629983) | Cod sursa (job #804260) | Cod sursa (job #1418636) | Cod sursa (job #1054284)
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
/** http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=lowestCommonAncestor
NOTATII (ca in articol)
-----------------------
C: lista de fii a arborelui
M: dinamica pt. RMQ
N: nr. noduri
Q: nr. intrebari (query-uri)
E: vectorul cu nodurile vizitate in parcurgerea Euler
nrE: nr. elemente ale lui E si L
Log: vector cu logaritmi precalculati ( Log[i] == floor(log2(i)) )
H: H[i] este primul index al nodului i in E
L: L[i] este nivelul nodului E[i]
u, v: se citesc Q intrebari de forma "care este LCA al nodurilor u si v?"
FUNCTIONARE
-----------
-> Se da un arbore prin vectorul de tati. Parcurgerea Euler presupune vizitarea
unui fiu plecand din tatal sau, ceea ce un vector de tati nu permite.
-> Daca fiecare nod ar avea acelasi numar de fii atunci s-ar putea reprezenta
ca un heap. In cazul general este necesara lista de fii. Aceasta se construieste
la citire (lista de adiacenta C).
-> Parcurgerea Euler va construi un vector de noduri vizitate ( E in program ) cu
2*N-1 elemente ( nrE in program ). Pe lista de fii, aceasta se realizeaza in timp
liniar ( O(nrE) ).
-> O data cu vectorul E se construiesc si vectorii L si H pe care se realizeaza RMQ.
-> RMQ construieste M-ul astfel: M[i][j] = nodul de nivel minim cuprins intre pozitiile
j si j + (1 << i) - 1 din reprezentarea Euler a arborelui (adica H).
-> rezultatul unui query (pt. nodurile u si v) este nodul de nivel minim cuprins intre
H[min(u, v)] si H[max(u, v)].
**/
const int MAX_N = 100005, MAX_L = 20;
int nrE, N, Q;
int L[MAX_N * 2], E[MAX_N * 2], Log[MAX_N * 2], H[MAX_N], M[MAX_L][MAX_N * 4];
vector <int> C[MAX_N];
typedef vector<int>::iterator IT;
void Euler(int nod, int niv) {
E[++nrE] = nod;
L[nrE] = niv;
H[nod] = nrE;
for(IT i = C[nod].begin(); i != C[nod].end(); i++) {
Euler(*i, niv + 1);
E[++nrE] = nod;
L[nrE] = niv;
}
}
void RMQ() {
for(int i = 2; i <= nrE; i++)
Log[i] = Log[i >> 1] + 1;
for(int i = 1; i <= nrE; i++)
M[0][i] = i;
for(int i = 1; (1 << i) < nrE; i++)
for(int j = 1; j <= nrE - (1 << i); j++) {
int l = 1 << (i - 1);
M[i][j] = M[i-1][j];
if(L[M[i-1][j + l]] < L[M[i][j]])
M[i][j] = M[i-1][j + l];
}
}
int query(int u, int v) {
int diff, l, sol, sh;
int a = H[u], b = H[v];
if(a > b) swap(a, b);
diff = b - a + 1;
l = Log[diff];
sol = M[l][a];
sh = diff - (1 << l);
if(L[sol] > L[M[l][a + sh]])
sol = M[l][a + sh];
return E[sol];
}
int main() {
FILE *in = fopen("lca.in", "r"), *out = fopen("lca.out", "w");
if (in && out) {
fscanf(in, "%d %d", &N, &Q);
for(int i = 2; i <= N; i++) {
int u;
fscanf(in, "%d", &u);
C[u].push_back(i);
}
Euler(1, 0);
RMQ();
for(int i = 0; i < Q; i++) {
int u, v;
fscanf(in, "%d %d", &u, &v);
fprintf(out, "%d\n", query(u, v));
}
fclose(in), fclose(out);
}
return 0;
}