How far away ?
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5810 Accepted Submission(s): 2182
Problem Description
There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.
Input
First line is a single integer T(T<=10), indicating the number of test cases.
For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.
For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.
Output
For each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.
Sample Input
2
3 2
1 2 10
3 1 15
1 2
2 3
2 2
1 2 100
1 2
2 1
Sample Output
10
25
100
100
题意:
给出 T(0 ~ 10) 组 case,每个 case 给出 N(2 ~ 40000) 个节点和 M (1 ~ 200)个询问,后给出 N - 1 条边的两节点和权值。每次询问输出一个答案,输出 a 到 b 的距离。
思路:
LCA。RMQ 的在线算法,任何一个根为起点都可以,dfs 的时候顺便用 dis 记录到根的距离,求出 a 和 b 的 LCA c,则距离等于 dis [ a ] + dis [ b ] - 2 X dis [ c ]。因为 RMQ 数组的长度开小了,所以 WA 了很多遍。
AC:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int VMAX = 40010;
const int EMAX = VMAX * 10;
int n, ind;
int next[EMAX], fir[VMAX], w[EMAX], v[EMAX];
int k;
int dis[VMAX], vs[VMAX * 5], dep[VMAX * 5], id[VMAX];
bool vis[VMAX];
int dp[VMAX * 5][25];
void init () {
ind = k = 0;
memset(fir, -1, sizeof(fir));
memset(vis, 0, sizeof(vis));
}
void add_edge (int f, int t, int val) {
v[ind] = t;
w[ind] = val;
next[ind] = fir[f];
fir[f] = ind;
++ind;
}
void dfs (int x, int d) {
id[x] = k;
vs[k] = x;
dep[k++] = d;
vis[x] = 1;
for (int e = fir[x]; e != -1; e = next[e]) {
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 - 1; ++i) {
int a, b, val;
scanf("%d%d%d", &a, &b, &val);
add_edge(a, b, val);
add_edge(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;
}