题干:

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

解题报告:

   没想到ccf的时候刚学的lca,,第二周实验室的题就用到了2333。。Tarjan的方法也学了一些抽空写了。

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 5e4 + 5;
bool vis[MAX];
int dep[MAX],fa[MAX][33],cost[MAX][33];

int n,m;
vector<int> vv[MAX];
vector<int> ww[MAX];
//int f[MAX][30],fa[MAX];
//void dfs(int cur) {
//	vis[cur] = 1;
//	int up = vv[cur].size();
//	for(int i = 0; i<up; i++) {
//		int v = vv[cur][i];
//		if(vis[v]) continue;
//		fa[v] = cur;
//		dep[v] = dep[cur]+1;
//		dfs(v);
//	}
//}
//void bz() {
//	for(int i = 1; i<=n; i++) f[i][0] = fa[i];
//	for(int j = 1; j<=30; j++) {
//		for(int i = 1; i<=n; i++) {
//			f[i][j] = f[f[i][j-1]][j-1];
//		}
//	}
//}
void dfs(int cur, int rt) {
  fa[cur][0] = rt;
  dep[cur] = dep[rt] + 1;
  for(int i = 1; i < 31; ++i) {
    fa[cur][i] = fa[fa[cur][i - 1]][i - 1];
    cost[cur][i] = cost[fa[cur][i - 1]][i - 1] + cost[cur][i - 1];
  }
  int sz = vv[cur].size();
  for (int i = 0; i < sz; ++i) {
    if (vv[cur][i] == rt) continue;
    cost[vv[cur][i]][0] = ww[cur][i];
    dfs(vv[cur][i], cur);
  }
}
int lca(int u,int v) {
	if(dep[u] < dep[v]) swap(u,v);
	int res = 0;
	int dc = dep[u]-dep[v];
	for(int i = 0; i<=30; i++) {
		if((1<<i) & dc) res += cost[u][i],u=fa[u][i];
	}
//  for (int j = 0; dc; ++j, dc >>= 1)
//    if (dc & 1) res += cost[u][j], u = fa[u][j];
	if(u == v) return res;
	for(int i = 30; i>=0 && u!=v; i--) {
		if(fa[u][i] != fa[v][i]) {
			res += cost[v][i] + cost[u][i]; 
			u=fa[u][i];
			v=fa[v][i];
		}
	}
	res += cost[u][0] + cost[v][0];	
	u=fa[u][0];
	return res;
}

//int lca(int x, int y) {
//  if (dep[x] > dep[y]) swap(x, y);
//  int tmp = dep[y] - dep[x], ans = 0;
//  for (int j = 0; tmp; ++j, tmp >>= 1)
//    if (tmp & 1) ans += cost[y][j], y = fa[y][j];
//  if (y == x) return ans;
//  for (int j = 30; j >= 0 && y != x; --j) {
//    if (fa[x][j] != fa[y][j]) {
//      ans += cost[x][j] + cost[y][j];
//      x = fa[x][j];
//      y = fa[y][j];
//    }
//  }
//  ans += cost[x][0] + cost[y][0];
//  return ans;
//}
int main()
{
	int t;
	cin>>t;
	while(t--) {
		scanf("%d%d",&n,&m);
		for(int i = 1; i<=n; i++) vv[i].clear(),ww[i].clear();
		for(int a,b,c,i = 1; i<=n-1; i++) {
			scanf("%d%d%d",&a,&b,&c);
			vv[a].pb(b);
			vv[b].pb(a);
			ww[a].pb(c);
			ww[b].pb(c);
		}
		dfs(1,-1);
		while(m--) {
			int a,b;
			scanf("%d%d",&a,&b);
			printf("%d\n",lca(a,b));
		}
	}
	

	return 0 ;
 }