题目描述
【题目】
有N个点,编号为1到N,有N-1条边,每条边都有长度。
有若干个操作,操作分为两种
第一种:DIST u,v 表示询问u到v的距离。
第二种:KTH u,v,k 表示询问从u到v路径上第k个点的编号。
【输入格式】
输入一个整数T,表示有T组数据(1<=T<=25)
对于每组数据,第一行输入一个整数N,表示有N个点(1<=N<=10000)
下来N-1行每行输入三个整数x,y,c表示从编号为x的点到编号为y的点有一条长度为c的边。
下来若干个操作。读入“DONE”时停止。
操作详情见题目描述。
【输出格式】
对于每次操作输出相应答案即可。
【输入样例】
1
6
1 2 1
2 4 1
2 5 2
1 3 1
3 6 2
DIST 4 6
KTH 4 6 4
DONE
【输出样例】
5
3
因为不用在线修改,所以用LCA求解即可
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std ;
inline int read() {
int x = 0 , f = 0 ; char s = getchar() ;
while ( !isdigit(s) ) f |= s=='-' , s = getchar() ;
while ( isdigit(s) ) x = (x<<1)+(x<<3)+(s-48) , s = getchar() ;
return !f ? x : -x ;
}
const int N = 1e4 + 10 ;
struct edge {
int v , w , nxt ;
} e[N<<1] ; int tot , last[N] ;
inline void add ( int u , int v , int w ) {
e[++tot] = (edge){ v , w , last[u] } ;
last[u] = tot ;
e[++tot] = (edge){ u , w , last[v] } ;
last[v] = tot ;
}
int fa[N][20] , dis[N] , dep[N] ;
void dfs ( int u , int f ) {
fa[u][0] = f ; dep[u] = dep[f] + 1 ;
for ( int i = 1 ; (1<<i) < dep[u] ; i ++ )
fa[u][i] = fa[fa[u][i-1]][i-1] ;
for ( int i = last[u] ; i != -1 ; i = e[i].nxt ) {
int v = e[i].v ; if ( v == f ) continue ;
dis[v] = dis[u] + e[i].w ; dfs ( v , u ) ;
}
}
inline int LCA ( int x , int y ) {
if ( dep[x] < dep[y] ) swap ( x , y ) ;
for ( int i = 20 ; i >= 0 ; i -- )
if ( dep[x]-dep[y] >= (1<<i) )
x = fa[x][i] ;
if ( x == y ) return x ;
for ( int i = 20 ; i >= 0 ; i -- )
if ( (1<<i) < dep[x] && fa[x][i] != fa[y][i] )
x = fa[x][i] , y = fa[y][i] ;
return fa[x][0] ;
}
int find ( int x , int up ) {
if ( up == 0 ) return x ;
for ( int i = 20 ; i >= 0 ; i -- )
if ( (1<<i) <= up ) {
up -= (1<<i) ; x = fa[x][i] ;
if ( up == 0 ) break ;
}
return x ;
}
int main() {
int T ; T = read() ;
while ( T -- ) {
int n = read() , u , v , w ;
tot = -1 ; memset ( last , -1 , sizeof ( last )) ;
for ( int i = 1 ; i < n ; i ++ ) {
u = read() , v = read() , w = read() ;
add ( u , v , w ) ;
}
dfs ( 1 , 0 ) ;
char s[11] ;
while ( ~scanf("%s", s ) ) {
if ( s[1] == 'O' ) break ;
u = read() , v = read() ;
if ( s[1] == 'I' ) printf ( "%d\n" , dis[u]+dis[v]-(dis[LCA(u,v)]<<1) ) ;
else {
w = read() ; int t = LCA ( u , v ) ;
if ( dep[u]-dep[t]+1 < w ) {
w -= ( dep[u]-dep[t]+1 ) ;
printf ( "%d\n" , find(v,dep[v]-dep[t]-w) ) ;
}
else printf ( "%d\n" , find(u,w-1) ) ;
}
}
}
return 0 ;
}