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