Pagini recente » Cod sursa (job #1512987) | Cod sursa (job #2415013) | Cod sursa (job #2728161) | Cod sursa (job #2229831) | Cod sursa (job #2105635)
/*
lowest common ancestor
Solutie 70p
Vom folosi o matrice in care pentru fiecare nod vom retine stramosul situat cu 2^k nivele mai sus, unde 2^k<=n
Matricea va avea k linii si n coloane
Ea va fi notata a si va fi construita dinamic dupa formula
a[0][i]=i, unde i=1...n
a[k][i]=a[k-1][a[k-1][i]], i=1...n si k=1...logn
Cu alte cuvinte vom imparti inaltimea fiecarui nod in intervale puteri ale lui 2.
De exemplu daca un arbore are 10 noduri, ptr nodul 5 se vor retine stramosii situati cu 1 nivel mai sus, 2 nivele, 4 nivele, 8 nivele
Daca un stramos nu exista se va retine 0.
Pentru a gasi lca, vom inainta mai intai in matrice cu nodul de cel mai mare nivel
pana cand va ajunge pe acelasi interval(linie) cu al doilea. Daca am ajuns chiar in al doilea nod, avem raspunsul
Apoi vom inainta cu amandoi doar daca avem stramos pe acel nivel si nu este comun.
In final stramosul de pe linia 0 este raspunsul
Matricea fiilor o memoram in arb
Cu o parcurgere in adancime gasim nivelul fiecarui nod si il retinem in matricea nivel
Complexitate timp: dfs O(n), formarea matricei a in (n*log n), fiecare interogare in timp logaritmic O(log n),
in final O(n*log n) + O(m*log n), unde m este numarul de interogari
Complexitate spatiu : O(n*log n), marimea matricei a
*/
#include<fstream>
#include<vector>
#define dim 100005
using namespace std;
int nivel[dim],a[20][dim];
vector<int>arb[dim];
int n,m;
ifstream fin("lca.in");
ofstream fout("lca.out");
void citire()
{
int i,j;
fin>>n>>m;
for(i=2;i<=n;i++)
{
fin>>j;
a[0][i]=j;
arb[j].push_back(i);
}
}
void dfs(int nod,int niv)
{
nivel[nod]=niv;
for(vector<int>::iterator it=arb[nod].begin();it!=arb[nod].end();it++)
dfs(*it,niv+1);
}
int lca(int x, int y)
{
int i,powerx,powery;
//vedem care nod este pe un nivel mai mare si il retinem in x
//pp ca este x
//daca este y interschimb
if(nivel[x]<nivel[y])
x=x+y, y=x-y,x=x-y;
//trebuie sa stim de unde pornim explorarea in matrice, de pe ce linie
//calculam puterea maxima a lui 2 fata de nivelul lui x, respectiv y si retinem in powerx si powery
powerx=1;
while((1<<powerx)<nivel[x])
powerx++;
powery=1;
while((1<<powery)<nivel[y])
powery++;
//aducem x pe acelasi interval cu y
for(i=powerx;i>=0;i--)
if(nivel[x]-(1<<i)>=nivel[y])
x=a[i][x];
//daca am ajuns in y avem stramosul comun de nivel maxim
if(x==y)
return x;
//gasim stramosul comun
for(i=powery;i>=0;i--)
if(a[i][x]!=0 && a[i][x]!=a[i][y])
{
x=a[i][x];
y=a[i][y];
}
return a[0][x];
}
int main()
{
int i,k,x,y;
citire();
dfs(1,0);
//construim matricea a
for(k=1;(1<<k)<=n;k++)
for(i=1;i<=n;i++)
a[k][i]=a[k-1][a[k-1][i]];
//realizam cele m query
for(i=1;i<=m;i++)
{
fin>>x>>y;
fout<<lca(x,y)<<"\n";
}
return 0;
}