Pagini recente » Cod sursa (job #1012078) | Cod sursa (job #5705) | Cod sursa (job #2750751) | Cod sursa (job #169656) | Cod sursa (job #2969164)
//este problema lowest common ancestor de pe infoarena
//arborele este dat prin vector de tati, iar 1 este mereu radacina
//vom prezenta aici metoda de a determina lca-ul folosind o lista, pentru fiecare
//nod stocand ce nod se afla mai sus de e cu 1, 2, 4, 8, ... pozitii
//mai intai, aducem nodurile u si v pentru care vrem sa determinam lca-ul
//la acelasi nivel in arbore, urmand sa aflam lca pt u' si v'.
//cautam binar in sus si cand gasim cele mai de sus noduri care nu coincid pt u si v
//aducem u si v fix in acele pozitii
//rezolvarea aceasta NU AR OBTINE PUNCTAJ MAXIM PE INFOARENA, deoarece n este prea mare...
#include <bits/stdc++.h>
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
int n, t;
vector<int> adi[10001];
int dpth[10001];
vector<int> ancestors[10001]; // tine minte stramosii pe pozitii puteri ale lui 2
void citire() {
fin >> n >> t;
int a;
for(int i = 2; i <= n; i++) {
fin >> a;
adi[a].push_back(i);
ancestors[i].push_back(a); // stramosul cu 1 mai sus (tatal) (2^(0) --> pozitia 0 in vector)
//cout << "--" << ancestors[i][0];
}
}
void calc_dpth(int nod, int d) {
dpth[nod] = d;
for(auto nou : adi[nod]) {
calc_dpth(nou, d + 1);
}
}
int main() {
citire();
//calculam adancimea la care se afla fiecare nod
calc_dpth(1, 0);
//cout << "a";
//acum stramosii cu 2^0 mai sus de fiecare nod sunt calculati. Vom calcula acum
//stramosii cu toate puterile mai sus, pana la 2^14
for(int putere = 1; putere < 14; putere++) {
//cout << "putere " << putere << "\n";
for(int nod = 1; nod <= n; nod++) {
//cout << "nod " << nod << ", ";
//verificam daca ne permite nodul de sus sa avansam (daca nodul cu putere mai sus are putere
//stramosi, ca poate are doar mai putini)
if(ancestors[nod].size() >= putere && ancestors[ancestors[nod][putere - 1]].size() >= putere) {
ancestors[nod].push_back(ancestors[ancestors[nod][putere - 1]][putere - 1]);
}
}
}
// for(int i = 1; i <= n; i++) {
// cout << "\n" << i << ": ";
// for(auto it : ancestors[i]) {
// cout << it << " ";
// }
// }
//citim query-urile
int u, v, dife;
for(int i = 1; i <= t; i++) {
fin >> u >> v;
//cout << i << ": " << u << ", " << v << "\n";
//aducem u si v pe aceeasi pozitie
if(dpth[u] < dpth[v]) {
dife = dpth[v] - dpth[u];
int putere = 0;
while(dife > 0) {
if(dife % 2 == 1) {
v = ancestors[v][putere];
}
dife /= 2;
putere++;
}
}
else if(dpth[v] < dpth[u]) {
//cout << "am intrat cu dife ";
dife = dpth[u] - dpth[v];
//cout << dife << "\n";
int putere = 0;
while(dife > 0) {
if(dife % 2 == 1) {
u = ancestors[u][putere];
putere++;
}
dife /= 2;
putere++;
//cout << u << "\n";
}
}
//acum nodurile au fost aduse pe aceeasi pozitie
//incepem cautarea de la cea mai mare putere a lui 2 mai mica su egala
//cu lungimea vecotrului de ancestori
//cout << "---" << u << ", " << v << "\n";
if(u == v) {
fout << u << "\n";
continue;
}
for(int putere = ancestors[u].size(); putere > 0; putere--) {
if(ancestors[u][putere - 1] != ancestors[v][putere - 1]) {
u = ancestors[u][putere - 1];
v = ancestors[v][putere - 1];
}
}
fout << ancestors[u][0] << "\n";
}
return 0;
}