版权声明:本博客内容基本为原创,如有问题欢迎联系,转载请注明出处 https://blog.csdn.net/qq_41955236/article/details/82785136
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=50005;
typedef long long ll;
int n,m,cnt,tot;
bool vis[maxn];
int head[maxn],deep[maxn*4],ind[maxn*4],first[maxn],dp[maxn*4][25];
ll dist[maxn];
struct node{
int to,next;
ll w;
}e[maxn*3];
inline ll read(){
char x=getchar(); ll num=0;
while(!(x>=48&&x<=57))
x=getchar();
while(x>=48&&x<=57)
num=num*10+x-48,x=getchar();
return num;
}
inline void add(int u,int v,ll w){
e[cnt].to=v;
e[cnt].next=head[u];
e[cnt].w=w;
head[u]=cnt++;
}
inline void dfs(int t,int dep){
vis[t]=1;
ind[++tot]=t;//给每个结点编号
deep[tot]=dep;
first[t]=tot;
for(int i=head[t];~i;i=e[i].next){
int v=e[i].to; ll w=e[i].w;
if(!vis[v]){
dist[v]=dist[t]+w;
dfs(v,dep+1);
}
ind[++tot]=t;
deep[tot]=dep;
}
}
inline void ST(int n){
for(int i=1;i<=n;i++) dp[i][0]=i;//保存最小深度下标
for(int j=1;(1<<j)<=n;j++){
for(int i=1;i+(1<<j)-1<=n;i++){
int a=dp[i][j-1],b=dp[i+(1<<(j-1))][j-1];
dp[i][j]=deep[a]>deep[b]?b:a;
}
}
}
inline int RMQ(int l,int r){
int k=0;
while((1<<(k+1))<=r-l+1) k++;
int a=dp[l][k],b=dp[r-(1<<k)+1][k];
return deep[a]>deep[b]?b:a;
}
inline int LCA(int u,int v){
int x=first[u],y=first[v];
if(x>y) swap(x,y);
int res=RMQ(x,y);
return ind[res];
}
inline void init(int n){
tot=cnt=0;
memset(head,-1,sizeof(int)*(n+1));
memset(vis,0,sizeof(vis));
}
int main(){
int T;
cin>>T;
while(T--){
n=read();int q=read();
init(n);
int x,y;
for(int i=1;i<n;i++){
x=read();y=read(); ll w=read();
add(x,y,w);
add(y,x,w);
}
dist[1]=0;
dfs(1,1);
ST(tot);
while(q--){
int a,b;
a=read();b=read();
int lca=LCA(a,b);
printf("%lld\n",dist[a]+dist[b]-2*dist[lca]);
}
}
return 0;
}