백준 1761 정점들의 거리

https://www.acmicpc.net/problem/2233

LCA와 LCA 도중에 나오는 level을 이용하면 쉽게 구할 수 있습니다.

트리

0 base-level이 1에서부터의 거리이기 때문에

dist(a,b)=level[a]+level[b]-2level[LCA(a,b)]입니다. (y+z=(x+y)+(x+z)-2x)

자, 구현을 시작하죠!

#include<bits/stdc++.h>
#define SZ 40005
#define MX_H 20
using namespace std;
typedef pair<int,int> pii;
vector<pii> graph[SZ];
int lv[SZ];
int dp[MX_H][SZ];
int dis[SZ];
void dfs(int cur, int prt, int level, int dist){
	dis[cur] = dist;
	lv[cur] = level;
	dp[0][cur] = prt;
	int l = graph[cur].size();
	for(int i=0;i<l;i++){
		int next = graph[cur][i].first; int ndis = graph[cur][i].second;
		if(prt!=next) dfs(next,cur,level+1,dist+ndis);
	}
}
int level_up(int x, int d){
	for(int i=MX_H-1;i>=0;i--){
		if(d&(1<<i)) x=dp[i][x];
	}
	return x;
}
int main(void){
	int n; scanf("%d",&n);
	for(int i=0;i<n-1;i++){
		int a,b,c; scanf("%d %d %d",&a,&b,&c);
		graph[a].push_back(make_pair(b,c));
		graph[b].push_back(make_pair(a,c));
	}
	dfs(1,0,0,0);
	for(int i=1;i<MX_H;i++){
		for(int j=1;j<=n;j++){
			dp[i][j]=dp[i-1][dp[i-1][j]];
		}
	}
	int m; scanf("%d",&m);
	for(int i=0;i<m;i++){
		int x,y; scanf("%d %d",&x,&y);
		int nx = level_up(x,max(lv[x]-lv[y],0));
		int ny = level_up(y,max(lv[y]-lv[x],0));
		for(int i=MX_H-1;i>=0;i--){
			if(dp[i][nx]!=dp[i][ny]){
				nx=dp[i][nx];
				ny=dp[i][ny];
			}
		}
		if(nx!=ny){
			nx = dp[0][nx]; ny = dp[0][ny];
		}
		printf("%d\n",dis[x]+dis[y]-2*dis[nx]);		
	}
	return 0;
}