Pagini recente » Cod sursa (job #710210) | Cod sursa (job #1221195) | Cod sursa (job #214962) | Cod sursa (job #3184163) | Cod sursa (job #3254190)
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
ifstream in ("lca.in");
ofstream out ("lca.out");
const int NMAX = 1e5;
int n,q;
int log[NMAX], A[18][NMAX], rang[NMAX];
vector<int> G[NMAX];
void precalc() {
//precalc log intreg in baza 2
for (int i = 2; i <= n; i++)
log[i] = log[i/2] + 1;
//precalc matricea tatiilor de oridin 2^k, unde a[j][i] este al 2^j lea stramos al lui i
for (int j = 1; (1 << j) <= n; j++)
for (int i = 1; i <= n; i++) {
A[j][i] = A[j-1][A[j-1][i]]; //adica stramosul stramosului de ordin 2^k
}
}
void printMat (int A[][NMAX]) {
for (int i = 0; (1 << i) <= n; i++, cout << '\n')
for (int j = 1; j <= n; j++)
cout << A[i][j]<< " ";
/* n = 11, stramosi de grad 2^k
0 1 1 2 2 2 4 4 6 3 3
0 0 0 1 1 1 2 2 2 1 1
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
*/
}
void dfs(int nod, int lev)
{
//dfs initial pentru rangul fiecarui nod in arbore
rang[nod] = lev;
for (auto v: G[nod])
dfs(v, lev+1);
}
int lca(int x, int y)
{
if(rang[x] < rang[y])
swap(x, y);
// lifting y to x
int log1, log2;
for(log1 = 1; (1 << log1) < rang[x]; ++log1);
for(log2 = 1; (1 << log2) < rang[y]; ++log2);
for(int k = log1; k >= 0; --k)
if(rang[x] - (1 << k) >= rang[y])
x = A[k][x];
if(x == y) return x;
/*
de la acelasi nivel, lift amandoi pana gasim stramosi comun
Se formeaza o suma crescatoare din puteriile lui 2 incercand sa maximizam pasii
*/
for(int k = log2; k >= 0; --k)
if(A[k][x] && A[k][x] != A[k][y])
x = A[k][x],
y = A[k][y];
return A[0][x];
}
int main()
{
in >> n >> q;
for (int i = 2; i <= n; i++) { //radaina este specificata, anume 1
in >> A[0][i]; //citim prima linie de stramosi
G[A[0][i]].push_back(i); //abore orientat cu susul in jos (sensul parcurgerii dfs)
}
precalc();
dfs(1, 0);
for(int x, y; q; q--)
{
in >> x >> y;
out << lca(x, y) << "\n";
}
printMat(A);
return 0;
}