原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586
题意:n个点,编号1-n,接下来n-1行,每行三个数字表示两点之间的距离,题目是保证两点间不会出现两条可行的路,也就是不会有环;m条询问,每条询问两个数字a,b表示a,b的最短距离。
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<vector>
#include<cstring>
#include<queue>
#include<stack>
#include<algorithm>
#include<cmath>
#define INF 99999999
#define eps 0.0001
using namespace std;
struct Edge
{
int w;
int v;
int next;
};
int t;
int n, m;
int cnt;
Edge edge[40005 * 2];
int head[40005];
int x[40005];
int y[40005];
int z[40005];
int pre[40005];
int dist[40005];
bool vis[40005];
void add(int u, int v, int w)
{
edge[cnt].w = w; edge[cnt].v = v; edge[cnt].next = head[u]; head[u] = cnt++;
edge[cnt].w = w; edge[cnt].v = u; edge[cnt].next = head[v]; head[v] = cnt++;
}
int find(int x)
{
if (pre[x] != x)
return pre[x] = find(pre[x]);
return x;
}
void tarjan(int u)
{
vis[u] = 1;
pre[u] = u;
for (int i = 0; i < m; i++)
{
if (x[i] == u&&vis[y[i]]) z[i] = find(y[i]);
if (y[i] == u&&vis[x[i]]) z[i] = find(x[i]);
}
for (int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].v;
if (!vis[v])
{
dist[v] = dist[u] + edge[i].w;
tarjan(v);
pre[v] = u;
}
}
}
int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d%d", &n, &m);
int u, v, w;
cnt = 0;
memset(head, -1, sizeof(head));
for (int i = 1; i < n; i++)
{
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
}
for (int i = 0; i < m; i++)
{
scanf("%d%d", &u, &v);
x[i] = u;
y[i] = v;
}
memset(vis, 0, sizeof(vis));
dist[1] = 0;
tarjan(1);
for (int i = 0; i < m; i++)
printf("%d\n", dist[x[i]] + dist[y[i]] - 2 * dist[z[i]]);
}
return 0;
}