//倍增算法求lca,预处理是o(n),查询是o(m*logn);
//tarjan算法离线求lca预处理是o(n),查询是o(m);
//一个是o(n+m*logn),一个是o(n+m)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
typedef pair<int,int>PII;
const int N=10010;
const int M=2*N;
int n,m; //n个点数,m个询问个数
int h[N],e[M],ne[M],w[M],idx; //邻接表
int st[N]; //记录当前点的状态,如果状态为2表示已经搜索完并且回溯了
//状态为1说明正在搜索,状态为0说明还没搜索,这里st数组要开N,表示N个结点的状态
vector<PII>all[N]; //存储所有的查询,对于每个查询存储两个lca(a,b)和lca(b,a);
int dist[N]; //存储每个结点到根节点的距离
int fa[N]; //存储每个点的父节点,如果路径压缩的话其实是找每个结点的祖宗节点
int res[M];
//并查集的查找操作
int find(int x){
if(x==fa[x])return x;
else return fa[x]=find(fa[x]); //路径压缩
}
//邻接表加边函数
void add(int a,int b,int c){
e[idx]=b;
w[idx]=c;
ne[idx]=h[a];
h[a]=idx;
idx++;
}
// //通过深搜初始化每个结点到根节点的距离
void dfs(int x,int fa){
//遍历所有边
for(int i=h[x];i!=-1;i=ne[i]){
int j=e[i];
if(j!=fa){
dist[j]=dist[x]+w[i]; //这里不同于求深度,是求距离
dfs(j,x);
}
}
}
void tarjan(int u){
st[u]=1;
//遍历所有边
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
//如果这个点还没有搜索过
if(!st[j]){
tarjan(j);
fa[j]=u;
}
}
//遍历关于这个点的所有询问
for(int i=0;i<all[u].size();i++){
int a=all[u][i].first,b=all[u][i].second;
if(st[a]==2){
int anc=find(a);
res[b]=dist[a]+dist[u]-2*dist[anc];
}
}
st[u]=2;
}
int main(){
//用邻接表存储树,首先初始化头结点
memset(h,-1,sizeof h);
scanf("%d%d",&n,&m);
//初始化并查集
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=n-1;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
for(int i=1;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
all[a].push_back({b,i});
all[b].push_back({a,i}); //存储另外一个点,和查询的编号
}
dfs(1,-1); //任选一个结点作为根节点,它这个方法可以不用一个st数组来记录
//是否搜索过这个点了
tarjan(1);
//输出所有查询
for(int i=1;i<=m;i++){
printf("%d\n",res[i]);
}
return 0;
}