/*少说话,多做事*/
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stdlib.h>
//#include<bits/stdc++.h>
//ios::sync_with_stdio(0);
//cin.tie(0);
//cout.tie(0);
typedef long long ll;

using namespace std;

/*
 第一行:n (n头牛)(1-5e4)    Q(询问次数)1-2e5

 接下来n行:牛的高度(1-2e5)

 接下来Q行 Q次询问
 m行(m次询问)i j : 表示i与j之间的距离是多少

 DFS+ST:将树看成一个无向图,u和v的公共祖先一定在u和v之间的最短路径上,
 (1)DFS:从树T的根开始,进行深度优先遍历(将树看成一个无向图),并记录好每次到达的顶点。
 由于每条边恰好经历两次,所以一共记录了2n-1个点,用E[1~2n-1]来表示
 (2)计算R:用R[i]表示E数组中第一个值为i的元素下标
 如果R[u]<R[v],DFS访问的顺序是E[R[u],R[u]+1,....R[v]].
 虽然其中包含u的后代,但深度最小的还是u与v的公共祖先
 (3)RMQ:计算RMQ
 当R[u]>=R[v]时,LCA[T,u,v]=RMQ(L,R[v],R[u])
 否则:          LCA[T,u,v]=RMQ(L,R[u],R[v])
 */


const int VMAX = 40010;
const int EMAX = VMAX * 10;

int n, ind;
int net[EMAX], fir[VMAX], w[EMAX], v[EMAX];


int dis[VMAX], vs[VMAX * 5], dep[VMAX * 5], id[VMAX];
bool vis[VMAX];

int dp[VMAX * 5][25];

int k;
void init ()
{
    ind = k = 0;
    memset(fir, -1, sizeof(fir));
    memset(vis, 0, sizeof(vis));
}

void addedge (int f, int t, int val)
{
    v[ind] = t;
    w[ind] = val;
    net[ind] = fir[f];
    fir[f] = ind++;
}


void dfs (int x, int d)
{
    id[x] = k; //k从0开始        id数组:x的序号是什么
    vs[k] = x;                //vs数组:第k个是x
    dep[k] = d;
    k++;
    vis[x] = 1; //标记已经遍历过

    for (int e = fir[x]; e != -1; e = net[e]) //遍历跟x节点相连的节点
    {
        int V = v[e];
        if (!vis[V])
        {
            dis[V] = dis[x] + w[e];
            dfs(V, d + 1);
            vs[k] = x;
            dep[k++] = d;
        }
    }
}

void RMQ_init ()
{
    for (int i = 0; i < k; ++i) dp[i][0] = i;

    for (int j = 1; (1 << j) <= k; ++j)
    {
        for (int i = 0; i + (1 << j) - 1 < k; ++i)
        {
            int a = dp[i][j - 1];
            int b = dp[i + (1 << (j - 1))][j - 1];
            if (dep[a] > dep[b]) dp[i][j] = b;
            else dp[i][j] = a;
        }
    }
}

int RMQ (int L, int R)
{
    int len = 0;
    while ((1 << (len + 1)) <= (R - L + 1)) ++len;

    int a = dp[L][len];
    int b = dp[R - (1 << len) + 1][len];

    if (dep[a] > dep[b]) return b;
    return a;
}

int LCA (int a, int b)
{
    int L = min(id[a], id[b]);
    int R = max(id[a], id[b]);
    int Min = RMQ(L, R);
    return vs[Min];
}

int main ()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        init();
        int m;
        scanf("%d%d", &n, &m);
        for (int i=1;i<n;i++)
        {
            int a, b, val;
            scanf("%d%d%d", &a, &b, &val);
            addedge(a, b, val);
            addedge(b, a, val);   //添加双向边
        }
        dfs (1, 1); //从根节点开始,遍历
        RMQ_init();
        while (m--)
        {
            int a, b;
            scanf("%d%d", &a, &b);

            int node = LCA(a, b);
            printf("%d\n", dis[a] + dis[b] - 2 * dis[node]);
        }

    }

    return 0;
}