Pagini recente » Cod sursa (job #2152074) | Cod sursa (job #2721087) | Cod sursa (job #3162634) | Cod sursa (job #303762) | Cod sursa (job #2189057)
#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 * 2], lg, nivelNod[DMAX * 2], pozInRepr[DMAX * 2];
int lungLog[DMAX * 2], nrIntervale;
int minim[27][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 * 2], primul, ultimul;
bool viz[DMAX * 2];
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 * 2], vfStiva;
bool viz[DMAX * 2];
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();
// for(int i = 1; i<= lg; i++){
// out << reprezEuler[i] <<' ';
// }
// out << '\n';
// for(int i = 1; i<= n; i++){
// out << pozInRepr[i] <<' ';
// }
lungimi();//incep sa fac rmq pe reprezentarea euleriana
sparseTable();
// for(int i = 0; i <= nrIntervale; i++){
// for(int j = 1; j <= lg; j++){
// out << minim[i][j] <<' ';
// }
// out << '\n';
// }
rezolvare();
return 0;
}