hdu 2586
How far away ?
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 30216
Accepted Submission(s): 12180
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
题目大意:首先给你一棵树,然后有多次询问 a,b之间距离,你对于每次询问,都要回答,两点之间距离是多少。
看到题目,我们不难想到用LCA解决。(然后就A了)
不懂LCA? 请到LCA详解快速入门。
因为题目给的是一棵树,所以路径只有一条,所以不存在最短路这个说法,我们可以先求出这两个点之间的LCA 然后稍微推一下公式可得:
res = d[x] + d[y] - 2 * d[lca] ;
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N=40010;
int T,n,m,head[N],nex[N<<1],to[N<<1],w[N<<1],tot,f[N][20],h[N],lg[N],d[N];
void add(int a,int b,int c){
w[++tot]=c; to[tot]=b; nex[tot]=head[a]; head[a]=tot;
}
void dfs(int x,int fa){
h[x]=h[fa]+1; f[x][0]=fa;
for(int i=1;(1<<i)<=h[x];i++) f[x][i]=f[f[x][i-1]][i-1];
for(int i=head[x];i;i=nex[i]){
if(to[i]!=fa){
d[to[i]]=d[x]+w[i]; dfs(to[i],x);
}
}
}
int LCA(int x,int y){
if(h[x]<h[y]) swap(x,y);
while(h[x]>h[y]) x=f[x][lg[h[x]-h[y]]-1];
if(x==y) return x;
for(int i=lg[h[x]]-1;i>=0;i--)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
int main(){
cin>>T;
for(int i=1;i<N;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
while(T--){
cin>>n>>m; tot=0; memset(head,0,sizeof head);
for(int i=1;i<n;i++){
int u,v,w; cin>>u>>v>>w; add(u,v,w); add(v,u,w);
}
dfs(1,0);
while(m--){
int x,y; cin>>x>>y; int lca=LCA(x,y);
cout<<d[x]+d[y]-2*d[lca]<<endl;
}
}
return 0;
}