Description
Description
村庄里有N个机房和连接它们的一些双向道路。机房从1标记到N。f*x每天都会从某一个机房去另一个机房切水题。所以他每天都要问:“如果我想从A机房去B机房有多远”?一般情况下,这些问题很难回答。但幸运的是,在这个村庄,答案总是独一无二的,因为这些道路都是建立在每两个机房之间的的简单道路(“简单”意味着你不能访问一个地方两次)。你的任务是回答f*x的问题。
Input
第一行是单个整数T(T <= 10),表示测试用例的个数。对于每个测试用例,在第一行中有两个数字n(2 <= n <= 40000)和m(1 <= m <= 200),表示机房数量和查询数量。以下n-1行各包含三个数字i,j,k,分开一个空格,意味着有一条连接机房i和机房j的道路,长度为k(0 <k <= 40000)。接下来的m行有两个整数i和j,请你回答机房i和房子j之间的距离。
Output
对于每个测试用例,输出m行。每一行代表f*x查询的答案。
Input
2
3 2
1 2 10
3 1 15
1 2
2 3
2 2
1 2 100
1 2
2 1
-
Sample Input
10
25
100
100
-
Sample Output
-
LCA,树形结构中两点之间的距离为dis[x]+dis[y]-2*dis[lca(x,y)]。
-
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #define SIZE 40010 using namespace std; struct edge // 一条边的结构 { int to, dis; }; struct qedge // 一个问题的结构 { int to, id; }; queue<int> q; vector<edge> graph[SIZE]; // 存图 vector<qedge> qgraph[SIZE]; // 存询问 int pre[SIZE], lca[SIZE], dis[SIZE], qx[SIZE], qy[SIZE]; bool visited[SIZE]; int find(int x) // 找祖先 { return (pre[x] != x) ? pre[x] = find(pre[x]) : x; } void tarjan(int u, int pr) // 离线算法 { int i, v; for (i = 0; i < graph[u].size(); ++i) // 美剧儿子 { v = graph[u][i].to; if (v == pr) // 保证v是儿子,不是前驱 { continue; } tarjan(v, u); // 递归 pre[v] = u; } visited[u] = true; // 标记 for (i = 0; i < qgraph[u].size(); ++i) // 寻找询问 { v = qgraph[u][i].to; if (visited[v]) // 两个点都找到了? { lca[qgraph[u][i].id] = find(v); // 存储结果 } } return; } void doit(void) { int n, m, k, i, x, y, w, u, v; scanf("%d%d", &n, &k); for (i = 1; i <= n; ++i) // 初始化 { graph[i].clear(); qgraph[i].clear(); pre[i] = i; } memset(visited, false, sizeof (visited)); for (i = 1; i < n; ++i) // 建图 { scanf("%d%d%d", &x, &y, &w); graph[x].push_back({y, w}); graph[y].push_back({x, w}); } for (i = 1; i <= k; ++i) // 询问图 { scanf("%d%d", &qx[i], &qy[i]); qgraph[qx[i]].push_back({qy[i], i}); qgraph[qy[i]].push_back({qx[i], i}); } q.push(1); visited[1] = true; while (!q.empty()) // BFS求距离(不要SPFA) { u = q.front(); q.pop(); for (i = 0; i < graph[u].size(); ++i) { v = graph[u][i].to; if (!visited[v]) { visited[v] = true; q.push(v); dis[v] = dis[u] + graph[u][i].dis; } } } memset(visited, false, sizeof (visited)); tarjan(1, -1); // 找LCA for (i = 1; i <= k; ++i) { printf("%d\n", dis[qx[i]] + dis[qy[i]] - (dis[lca[i]] << 1)); // 计算距离 } return; } int main(void) { int t; scanf("%d", &t); // 多组数据 while (t--) { doit(); } return 0; }