Pagini recente » Cod sursa (job #622464) | Cod sursa (job #576042) | Cod sursa (job #212262) | Cod sursa (job #1919626) | Cod sursa (job #2188939)
#include <iostream>
#include <fstream>
#include <cstring>
#define DMAX 100001
using namespace std;
ifstream in("lca.in");
ofstream out("lca.out");
struct elem{
int val;
elem *urm;
}* nod[DMAX];
int n, m;//date de intrare
int reprezEuler[DMAX * 4], lg, nivelNod[DMAX], pozInRepr[DMAX];
int lungLog[DMAX], nrIntervale;
int minim[17][DMAX * 4];
void citire(){
in >> n >> m;
for(int i = 2; i <= n; i++){
int tata;
in >> tata;//citesc tatal nodului i;
elem * deAdaugat = new elem;
deAdaugat -> val = i;
deAdaugat -> urm = nod[tata];
nod[tata] = deAdaugat; // fac legatura
}
}
void niveleNoduri(){
int coada[DMAX], primul, ultimul;
bool viz[DMAX * 4];
memset(viz, false, sizeof(viz));
primul = ultimul = 1;
coada[1] = 1;
viz[1] = true;//nodul 1 e radacina
nivelNod[1] = 0;
while(primul <= ultimul){
int actual = coada[primul];
primul++;//scot din coada
elem * parcurg = nod[actual];
while(parcurg != NULL){
if(viz[parcurg -> val] == false){
coada[++ ultimul] = parcurg -> val;
viz[parcurg -> val] = true;
nivelNod[parcurg -> val] = nivelNod[actual] + 1;
}
parcurg = parcurg -> urm;
}
}
}
void reprezentareEuleriana(){ //parcurgere DF
int stiva[DMAX * 4], vfStiva;
bool viz[DMAX];
memset(viz, false, sizeof(viz));
vfStiva = 1;
stiva[1] = 1;//1 e radacina
reprezEuler[++lg] = 1;
pozInRepr[1] = 1;
viz[1] = true;
while(vfStiva != 0){
int actual = stiva[vfStiva];
bool ok = false;
elem * parcurg = nod[actual];
while (parcurg != NULL){
if(viz[parcurg -> val] == false){
stiva[++vfStiva] = parcurg -> val;
viz[parcurg -> val] = true;
reprezEuler[++lg] = parcurg -> val;
if(pozInRepr[parcurg -> val] == 0){
pozInRepr[parcurg -> val] = lg;
}
ok = true;
break;
}
parcurg = parcurg -> urm;
}
if(ok == false){
vfStiva--;
reprezEuler[++lg] = stiva[vfStiva];
}
}
}
void lungimi(){
for(int i = 1; i <= lg; i++){
lungLog[i] = lungLog[i/2] + 1;
}
nrIntervale = lungLog[lg] - 1;
}
void sparseTable(){
for(int i = 1; i <= lg; i++){
minim[0][i] = reprezEuler[i];
}
for(int exLgInter = 1; exLgInter <= nrIntervale; exLgInter++){ //exponentii lgInter
int limita = 1 << exLgInter;
for(int index = 1; index + limita <= lg + 1; index++){
int lin = exLgInter, col = index;
if(nivelNod[minim[lin - 1][col]] < nivelNod[minim[lin - 1][col + (1 << (exLgInter - 1))]]){
minim[lin][col] = minim[lin - 1][col];
}else{
minim[lin][col] = minim[lin - 1][col + (1 << (exLgInter - 1))];
}
}
}
}
void rezolvare(){
for(int i = 1; i <= m; i++){
int a, b, st, dr;
in >> a >> b;
if(pozInRepr[a] < pozInRepr[b]){
st = pozInRepr[a];
dr = pozInRepr[b] + 1;
}else{
st = pozInRepr[b];
dr = pozInRepr[a] + 1;
}
int lungimeInterval = dr - st;
int incadrare = lungLog[lungimeInterval] - 1;
int min1, min2;
min1 = minim[incadrare][st];
min2 = minim[incadrare][dr - (1 << incadrare)];
if(nivelNod[min1] < nivelNod[min2]){
out << min1 << '\n';
}else{
out << min2 << '\n';
}
}
}
int main() {
citire();
niveleNoduri();
reprezentareEuleriana();
lungimi();//incep sa fac rmq pe reprezentarea euleriana
sparseTable();
rezolvare();
return 0;
}