题干:
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 ;
}