Solução Informática Avançado - Semana 50 - Problema 2

Chamemos as folhas iniciais de A e B. Para sabermos em que folha as lagartas se encontram, é necessário que primeiro encontremos o lca de A e B. Temos que tam_1 é a distância entre a folha A e o lca(A, B), e que tam_2 é a distância entre a folha B e o lca(A, B). Logo, a distância total entre as lagartas é dist = (tam_1+tam_2), e a distância que cada uma das lagartas deverá percorrer é k = \frac{dist}{2}. Depois de calcularmos essa distância, subimos na árvore o vértice que possui tam \leq k por k níveis (utilizamos a matriz do lca para isso). Chamaremos esse vértice de r. Caso dist seja par, significa que as lagartas se encontrarão num mesmo vértice, o vértice r. Caso contrário, significa que as lagartas se encontrarão em vértices vizinhos, sendo esses r e o pai de r.

Código para melhor entendimento:

#include <bits/stdc++.h>
#define pb push_back
#define MAXN 5010
using namespace std;
int n, lca[MAXN][25], nivel[MAXN];
vector < vector < int > > grafo;
inline void dfs(int u, int pai)
{
lca[u][0] = pai;
nivel[u] = nivel[pai]+1;
for(int i = 1 ; i <= 20 ; i++)
{
if(lca[u][i-1] != -1) lca[u][i] = lca[lca[u][i-1]][i-1];
}
for(int i = 0 ; i < grafo[u].size() ; i++)
{
int v = grafo[u][i];
if(v != pai) dfs(v, u);
}
}
inline int funclca(int a, int b) //funcao que calcula o lca
{
if(nivel[b] > nivel[a]) swap(a, b);
for(int i = 20 ; i >= 0 ; i--)
{
if(nivel[a] - (1 << i) >= nivel[b]) a = lca[a][i];
}
if(a == b) return a;
for(int i = 20 ; i >= 0 ; i--)
{
if((1 << i) < nivel[a] and (1 << i) < nivel[b] and lca[a][i] != lca[b][i])
{
a = lca[a][i];
b = lca[b][i];
}
}
return lca[a][0];
}
inline int funcvert(int a, int niv) //funcao que sobe o vertice
{
for(int i = 20 ; i >= 0 ; i--)
{
if(nivel[a] - (1 << i) >= niv) a = lca[a][i];
}
return a;
}
int main()
{
cin >> n;
grafo.resize(n+3);
memset(lca, -1, sizeof lca); //coloco todas as posições do lca como -1
for(int i = 0 ; i < n-1 ; i++)
{
int a, b;
cin >> a >> b;
grafo[a].pb(b);
grafo[b].pb(a);
}
nivel[0] = 0;
dfs(1, 0); // chamo a dfs que calcula-rá a matriz do lca e o nivel de cada um
int l;
cin >> l;
while(l--)
{
int a, b;
cin >> a >> b;
int r = funclca(a, b); //calculo o lca de a e b
int tam1 = nivel[a] - nivel[r], tam2 = nivel[b] - nivel[r]; //calculo a distancia das duas folhas ao lca
int resp = (tam1+tam2)/2; // distancia que cada um precisa percorrer até se encontrarem
if(nivel[a] > nivel[b]) r = funcvert(a, nivel[a] - resp); //verifico qual está mais distante do lca, subo ele
else r = funcvert(b, nivel[b] - resp); //até o resp-ésimo vertice
if((tam1+tam2)%2 == 0) cout << "As lagartas se encontram em " << r << ".\n"; //se a distancia for par, o vertice que elas se
else // é o r
{
int k1 = r, k2 = lca[k1][0]; //caso contrario, os vertices são o r e o pai de r
if(k2 < k1) swap(k1, k2);
cout << "As lagartas pularam para sempre a partir de " << k1 << " e " << k2 << ".\n";
}
}
} //10938uva
view raw noics5avp2.cpp hosted with ❤ by GitHub