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