http://acm.hdu.edu.cn/showproblem.php?pid=2586
题意:给出一颗n个节点,n-1边且有距离(带权),m次询问,问两点间最短距离。
解法:记录每一个节点到根节点(默认为1)距离,u、v两点距离为dis[u]+dis[v]-2*dis[fa].
//#include<bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <string>
#include <stdio.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string.h>
#include <vector>
#define ME(x , y) memset(x , y , sizeof(x))
#define SC scanf
#define rep(i , j , n) for(int i = j ; i <= n ; i++)
#define red(i , n , j) for(int i = n ; i >= j ; i--)
#define INF 0x3f3f3f3f
#define mod 1000000007
#define PI acos(-1)
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
typedef long long ll ;
const int maxn = 4e4+9;
int head[maxn] , qhead[maxn] , tol , qtol , vis[maxn] , f[maxn] , ans[maxn] , dis[maxn];
int n , m ;
struct node{
int to , next , w;
}g[maxn<<1];
struct query{
int to , next , id;
}q[maxn];
void init(){//初始化
ME(head , 0);
ME(qhead , 0);
ME(vis , 0);
ME(dis , 0);
tol = 0 , qtol = 0;
rep(i , 1 , n){
f[i] = i ;
}
}
void add(int u , int v , int w){//建边
g[++tol] = {v , head[u] , w};
head[u] = tol ;
}
void qadd(int u , int v , int id){//需查询的两点
q[++qtol] = {v , qhead[u] , id};
qhead[u] = qtol;
}
int find(int x){
return x == f[x] ? x :find(f[x]);
}
void unite(int u , int v){
f[v] = u ;
}
void dfs(int u , int d){
vis[u] = 1 ;
for(int i = head[u] ; i ; i = g[i].next){
int v = g[i].to;
dis[u] = d ;
if(vis[v]) continue;
dfs(v , d+g[i].w);
unite(u , v);
}
for(int i = qhead[u] ; i ; i = q[i].next){
int v = q[i].to;
if(vis[v]){
int fa = find(v);
ans[q[i].id] = dis[u] + dis[v] - 2*dis[fa];
}
}
}
void solve(){
cin >> n >> m ;
init();
rep(i , 1 , n-1){
int u , v , w ;
scanf("%d%d%d" , &u , &v , &w);
add(u , v , w);
add(v , u , w);
}
rep(i , 1 , m){
int u , v ;
scanf("%d%d" , &u , &v);
qadd(u , v , i);
qadd(v , u , i);
}
dfs(1 , 0);
rep(i , 1 , m){
cout << ans[i] << endl;
}
}
int main()
{
int t;cin >> t ;
while(t--){
solve();
}
return 0;
}