안녕하세요. 오늘은 트리와 쿼리 문제를 풀어볼 거예요.
https://www.acmicpc.net/problem/13511
이 문제는 그냥 함수를 여러개 만들면 됩니다.
LCA(x,y): x와 y의 최소 공통 조상을 반환
dist(x,y): y가 x의 조상임. x와 y의 거리
GetCost(x,y): y가 x의 조상임. x와 y사이의 비용
Kth(x,k): x의 k번째 조상
DFS(node,up): LCA를 만드는 DFS함수
또한 k번째 노드를 찾는것 또한 중요한데 자기자신이 첫번째 노드이고 k번째 노드가 lca를 기준으로 어디에 있는지를 잘 생각해야합니다.
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#define ll long long
using namespace std;
ll parent[101010][20] = { 0 }, depth[101010] = { 0 }, cost[101010][20] = {0};
vector <pair <ll, ll> > v[101010];
ll LCA(ll x, ll y) //x,y의 최소공통조상 찾기
{
if (depth[x] < depth[y]) swap(x, y);
for (ll i = 19; i >= 0; i--)
{
if (depth[parent[x][i]] >= depth[y])
x = parent[x][i];
}
if (x == y) return x;
for (ll i = 19; i >= 0; i--)
{
if (parent[x][i] != parent[y][i])
{
x = parent[x][i];
y = parent[y][i];
}
}
return parent[x][0];
}
ll dist(ll x, ll y) //y가 x의 조상이라는 전제하에 두 노드의 거리
{
ll ans = 0;
for (ll i = 19; i >= 0; i--)
{
if (depth[parent[x][i]] >= depth[y])
{
ans += pow(2, i);
x = parent[x][i];
}
}
return ans;
}
ll GetCost(ll x, ll y) //y가 x의 조상이라는 전제하에 두 노드사이의 비용
{
ll ans = 0;
for (ll i = 19; i >= 0; i--)
{
if (depth[parent[x][i]] >= depth[y])
{
ans += cost[x][i];
x = parent[x][i];
}
}
return ans;
}
ll Kth(ll x, ll k) //x의 k번 조상
{
for (ll i = 19; i >= 0; i--)
{
if (k >= pow(2, i))
{
k -= pow(2, i);
x = parent[x][i];
}
}
return x;
}
void DFS(ll node, ll up)
{
parent[node][0] = up;
depth[node] = depth[up] + 1;
for (ll i = 1; i <= 19; i++)
{
parent[node][i] = parent[parent[node][i - 1]][i - 1];
cost[node][i] = cost[node][i - 1] + cost[parent[node][i - 1]][i - 1];
}
for (auto i : v[node])
if (i.first != up)
{
cost[i.first][0] = i.second;
DFS(i.first, node);
}
}
int main(void)
{
ios_base::sync_with_stdio(false); cin.tie(NULL);
ll N, i, a, b, c;
cin >> N;
for (i = 0; i < N - 1; i++)
{
cin >> a >> b >> c;
v[a].push_back({ b,c });
v[b].push_back({ a,c });
}
DFS(1, 0);
ll M, type, x, y, z;
cin >> M;
for (i = 0; i < M; i++)
{
cin >> type;
if (type == 1)
{
cin >> x >> y;
ll lca = LCA(x, y);
cout << GetCost(x, lca) + GetCost(y, lca) << "\n";
}
else
{
cin >> x >> y >> z; z--;
ll lca = LCA(x, y);
ll dis = dist(x, lca);
if (z <= dis) //x-LCA의 경로에 k번째 노드가 있는 경우
{
cout << Kth(x, z) << "\n";
}
else
{
cout << Kth(y, dist(y, lca) - (z - dis)) << "\n";
}
}
}
}
감사합니다.