链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2586
题目:
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.
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个测试样例,每个测试样例开头给你一组n m
,n个点,m条询问,然后是n-1条边u v w
,u和v之间的路径长度为w,最后是m条询问,问你u v
之间的距离。
思路:
dfs一遍求出每个点到树根的距离,然后求出u和v的lca,两个点的距离就是cost[u] + cost[v] - 2 * cost[lca(u,v)]
。
实现:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
void read(int &x){ x=0;char c=getchar();while(c<'0' || c>'9')c=getchar();while(c>='0' && c<='9'){ x=x*10+c-'0';c=getchar(); }}
void write(int x){ int y=10,len=1;while(y<=x) {y*=10;len++;}while(len--){y/=10;putchar(x/y+48);x%=y;}}
using namespace std;
const int maxn = 40007;
int n, m, up[maxn][37], dep[maxn], _, cost[maxn];
bool vis[maxn];
vector<pair<int, int> > edge[maxn];
void addedge(int u, int v, int w) {
edge[u].emplace_back(v,w);
edge[v].emplace_back(u,w);
}
void dfs(int u, int d) {
dep[u] = d; vis[u] = true;
for(auto i : edge[u]) {
int v = i.first;
if (!vis[v]) {
cost[v] = cost[u] + i.second;
dfs(v, d + 1);
up[v][0] = u;
}
}
}
void process() {
for(int j=1 ; j<31 ; j++)
for(int i=1 ; i<=n ; i++)
if(up[i][j-1] != -1)/*if(up[i][j] != -1)*/
up[i][j] = up[up[i][j-1]][j-1];
}
int lca(int u, int v) {
if(dep[u] < dep[v]) swap(u,v);
int tmp = dep[u] - dep[v];
for(int j=0 ; j<31 && dep[u] != dep[v] ; j++) {
if(tmp & (1<<j))
u = up[u][j];
}
if(u == v) return v;
for(int j = 30 ; j>=0 ; j--) {
if(up[u][j] != up[v][j])
u = up[u][j], v = up[v][j];
}
return up[u][0];
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
read(_);
while(_--!=0) {
read(n),read(m);
memset(dep, -1, sizeof dep);
memset(up, -1, sizeof up);
memset(vis, 0, sizeof vis);
memset(cost, 0, sizeof cost);
for(int i=1, u, v, w ; i<n ; i++) {
read(u),read(v),read(w);
addedge(u,v,w);
}
dfs(1,1);
process();
for(int i=0, u, v ; i<m ; i++) {
read(u),read(v);
int tmp = lca(u,v);
write(cost[u]+cost[v]-cost[tmp]-cost[tmp]);
cout << '\n';
}
for(int i=0 ; i<=n ; i++) edge[i].clear();
}
return 0;
}