Pagini recente » Cod sursa (job #584358) | Cod sursa (job #439798) | Cod sursa (job #2515374) | Cod sursa (job #3144894) | Cod sursa (job #1420522)
// LCA - O(NlogN+M)
// LCA(x,y)este nodul de nivel minim intre primele aparitii
// ale nodurilor x si y in reprezentarea Euler a arborelui
#include <fstream>
#include <vector>
#include <bitset>
#define Nmax 100099
#define Emax 200099
#define LgMax 18
using namespace std;
ifstream f("lca.in");
ofstream g("lca.out");
int N, M;
vector < int > G[Nmax];
bitset < Nmax > viz;
/* E parcurgere Euler, Level[node] nivelul lui node
First[node] = prima aparitie a lui node in E[] */
int E[Emax], Level[Nmax], First[Nmax];
int lg[Emax],RMQ[LgMax][Emax],x,y;
/* Voi face o parcugere DSF si voi pune node la inceput si dupa fiecare fiu */
void DFS(const int& node, const int& level) {
viz[node] = 1;
E[ ++E[0] ] = node;
First[node]=E[0];
Level[node] = level;
for(vector<int>::iterator it = G[node].begin(); it != G[node].end(); ++it)
if(!viz[*it]) {
DFS(*it,level+1);
E[++E[0]]=node;
}
}
void buildRMQ() {
for(int i = 2; i <= E[0]; ++i) lg[i] = lg[i/2] + 1;
for(int j = 1; j <= E[0]; ++j) RMQ[0][j] = E[j];
for(int i = 1; (1<<i) <= E[0]; ++i)
for(int j = 1; j <= E[0]-(1<<i)+1; ++j)
{
int x = RMQ[i-1][j] , y = RMQ[i-1][j+(1<<(i-1))];
if(Level[x]<Level[y])RMQ[i][j]=x;
else RMQ[i][j]=y;
}
}
int LCA(const int& x, const int& y) {
int st = First[x], dr = First[y];
if(st > dr) swap(st,dr);
int i = lg[dr-st+1];
int x1=RMQ[i][st], x2 = RMQ[i][dr-(1<<i)+1];
if(Level[x1]<Level[x2])return x1;
else return x2;
}
int main()
{
f >> N >> M;
for(int i = 2; i <= N; ++i)
f >> x , G[x].push_back(i); /*ATENTIE citire speciala infoarena! */
DFS(1,1); /* parcurgere eulere */
buildRMQ();
for(int i=1;i<=M;++i) {
f >> x >> y;
g << LCA(x,y) << '\n';
}
f.close();g.close();
return 0;
}