#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; }