题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=2586
分析
数据规模较大,用Tarjan求LCA的方法来求树上两点间路径长度;
d i s ( x , y ) = d e p t h [ x ] + d e p t h [ y ] − 2 ∗ d e p t h [ l c a ( x , y ) ] dis(x, y) = depth[x] + depth[y] - 2 * depth[lca(x, y)] dis(x,y)=depth[x]+depth[y]−2∗depth[lca(x,y)]。
注意数组要开够,否则会报TLE???
AC代码
#include <cstdio>
#include <cstring>
inline int read() {
int num = 0;
char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9')
num = num * 10 + c - '0', c = getchar();
return num;
}
const int maxn = 4e4 + 5, maxm = 205;
int head[maxn], eid, point[maxn], qid;
struct Edge {
int v, w, next;
} edge[2 * maxn];
inline void insert(int u, int v, int w) {
edge[++eid].v = v;
edge[eid].w = w;
edge[eid].next = head[u];
head[u] = eid;
}
struct Query {
int id, x, next;
} query[2 * maxm];
inline void add(int id, int x, int y) {
query[++qid].id = id;
query[qid].x = y;
query[qid].next = point[x];
point[x] = qid;
}
int f[maxn], flag[maxn], d[maxn], ans[maxm];
int find(int x) {
if (x == f[x]) return x;
return f[x] = find(f[x]);
}
void tarjan(int u, int fa) {
flag[u] = 1;
for (int p = head[u]; p; p = edge[p].next) {
int v = edge[p].v, w = edge[p].w;
if (v == fa) continue;
d[v] = d[u] + w;
tarjan(v, u);
f[v] = u;
}
for (int p = point[u]; p; p = query[p].next) {
int id = query[p].id, x = query[p].x;
if (flag[x] == 2) ans[id] = d[u] + d[x] - 2 * d[find(x)];
}
flag[u] = 2;
}
int main() {
int t = read();
while (t--) {
memset(head, 0, sizeof(head));
memset(point, 0, sizeof(point));
memset(flag, 0, sizeof(flag));
eid = qid = 0;
int n = read(), m = read();
for (int i = 1; i < n; ++i) {
int u = read(), v = read(), w = read();
insert(u, v, w), insert(v, u, w);
}
for (int i = 1; i <= m; ++i) {
int x = read(), y = read();
add(i, x, y), add(i, y, x);
}
for (int i = 1; i <= n; ++i) f[i] = i;
tarjan(1, 0);
for (int i = 1; i <= m; ++i) printf("%d\n", ans[i]);
}
return 0;
}