#include<iostream>
#include<sstream>
#include<string>
#include<vector>
#include<list>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<algorithm>
#include<cmath>
#pragma warning(disable:4996)
using std::cin;
using std::cout;
using std::endl;
using std::stringstream;
using std::string;
using std::vector;
using std::list;
using std::pair;
using std::set;
using std::multiset;
using std::map;
using std::multimap;
using std::stack;
using std::queue;
class DisjoinSet
{
public:
vector<int>represent, rank;
DisjoinSet(const int &n) :represent(n), rank(n)
{
for (int i = 0; i < n; i++)
{
represent[i] = i;
}
}
int find(int i)
{
return represent[i] = represent[i] == i ? i : find(represent[i]);
}
void merge(const int &x, const int &y)
{
auto a = find(x); auto b = find(y);
if (rank[a] < rank[b])
{
represent[a] = b;
}
else
{
represent[b] = a;
if (rank[b] == rank[a])
{
rank[a]++;
}
}
}
};
class Tree
{
public:
int vertex;//树中的结点数
int edge;//树中的边树
vector<vector<pair<int,int>>>adjList;//邻接表,pair.first=destination vertex;pair.second=weight
map<pair<int, int>, pair<int, int>>lca;//结点first和second的最近公共祖先以及first到second的最短距离
Tree()
{
vertex = edge = 0;
}
Tree(const int &v,const int &e)
{
vertex = v;
edge = e;
adjList.resize(v + 1);
}
//当前遍历到的结点以及其到根的距离
void LRN_sub(vector<bool>&visited,DisjoinSet &union_set,int curvertex)
{
visited[curvertex] = true;
for (size_t i = 0; i < adjList[curvertex].size(); i++)
{
if (!visited[adjList[curvertex][i].first])
{
LRN_sub(visited, union_set, adjList[curvertex][i].first);
//子树的祖先为其父母
union_set.represent[adjList[curvertex][i].first] = curvertex;
}
}
for (int i = 1; i <= vertex; i++)
{
if (visited[i])
{
lca.insert({ {std::min(curvertex,i),std::max(curvertex,i) },{union_set.find(i),0} });
}
}
}
void dfs(vector<int>&distance,int curvertex)
{
for (size_t i = 0; i < adjList[curvertex].size(); i++)
{
distance[adjList[curvertex][i].first] = distance[i]+ adjList[curvertex][i].second;
dfs(distance, adjList[curvertex][i].first);
}
}
void LRN_main()
{
vector<bool>visited(vertex+1);//结点是否被访问过
DisjoinSet union_set(vertex + 1);
LRN_sub(visited, union_set, 1);
vector<int>distance(vertex + 1);//结点到根的距离
dfs(distance, 1);
for (int i = 1; i <= vertex; i++)
{
for (int j = i+1; j <= vertex; j++)
{
map<pair<int, int>, pair<int, int>>::iterator iter = lca.find({i,j});
iter->second.second = distance[iter->first.first] + distance[iter->first.second] - 2 * distance[iter->second.first];
}
}
}
};
int main()
{
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
int T; cin >> T;
while (T--)
{
int vertex, query;
cin >> vertex >> query;
Tree tree(vertex,vertex-1);
for (int i = 0; i < vertex-1; i++)
{
int first, second, weight;
cin >> first >> second >> weight;
tree.adjList[std::min(first, second)].push_back({ std::max(first,second),weight });
}
tree.LRN_main();
for (int i = 0; i < query; i++)
{
int first, second;
cin >> first >> second;
map<pair<int, int>, pair<int, int>>::iterator iter = tree.lca.find({ std::min(first,second),std::max(first,second) });
cout << iter->second.second << endl;
}
}
return 0;
}