题意: 给T组测试,每组n 个点,n-1 条边;求 m 对点的距离;
思路: 如果不懂 最近公共祖先这个概念,可以先去做 poj 1330 ,如果只是一对点(u,v),先一遍bfs 记录 每个节点的父亲节点;然后 从 u,v 往根节点走,
v = father[v]; u=father[u] ;知道第一次 u=v 此时 u (或者 v) 就是最近公共祖先; 时间复杂度 O( dep[u] + dep[v] )
当要查询多对(u,v) 时,单个单个的一一查询显然是超时;用一 parent[step][v] 去记录 节点v 往根节点走step 步之后 可以达到的节点 v' 的 父亲节点;
father [step + 1] = faher [step ] [ father[step][v] ] 当然 当达到根节点之后再继续走依旧是 -1 ;
反思:第一遍running error ,书本上是用dfs 写题想都没想 4000 个点,如果1 ……n 是一条直线,显然用递归爆栈;
另外题目表述又问题,他说要输出一空行,结果数据里面没有;
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<string>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<list>
#include<map>
#include<set>
using namespace std;
const int N = 40010;
const int lgN = 16;
int n, m;
struct P{
int to,val;
P(int to = 0, int val = 0):to(to), val(val) {}
};
vector <P> e[N];
int parent[lgN][N];
int dep[N];
int dist[N];
int Max_step;
struct Que{
int id,f;
Que(int id = 0,int f = 0):id(id), f(f) {}
};
void deal_init(){
for(int i = 1; i <= n; i++) e[i].clear();
int a,b,c;
for(int i = 1; i < n; i++){
scanf("%d%d%d",&a,&b,&c);
e[a].push_back(P(b,c));
e[b].push_back(P(a,c));
}
}
queue <Que> que;
void bfs(){
que.push(Que(1,-1));
dist[1] = 0;
dep[1] = 0;
while(!que.empty()){
Que cur = que.front();que.pop();
int i = cur.id;
parent[0][i] = cur.f;
vector <P> :: iterator it;
for(it = e[i].begin(); it != e[i].end(); it++){
if(it->to != cur.f){
dist[it -> to] = dist[i] + (it -> val);
dep[it -> to] = dep[i] + 1;
que.push(Que((it -> to), i ));
}
}
}
}
//void dfs(int i,int f,int Dep){
// parent[0][i] = f;
// dep[i] = Dep;
// vector <P> :: iterator it;
// for(it = e[i].begin(); it != e[i].end(); it++){
// int next = it -> to;
// if( next != f){
// dist[next] = dist[i] + it -> val;
// dfs(next, i, Dep+1);
// }
//
// }
//}
void deal_pre(){
// dist[1] = 0;
// dfs(1,-1,0);
bfs();
for(int step = 0; step < Max_step - 1; step++){
for(int i = 1 ;i <= n; i++){
if(parent[step][i] < 0) parent[step + 1][i] = -1;
else parent[step + 1][i] = parent[step][ parent[step][i] ];
}
}
}
int LCA(int u,int v){
if(dep[u] > dep[v]) swap(u,v);
for(int step = 0; step < Max_step; step++){
int dis = dep[v] - dep[u];
if( dis >> step & 1) v = parent[step][v];
}
if(u == v) return u;
for(int step = Max_step - 1; step >= 0; step--){
if(parent[step][u] != parent[step][v]){
u = parent[step][u];
v = parent[step][v];
}
}
return parent[0][u];
}
void work(){
int a,b;
while(m--){
scanf("%d%d",&a,&b);
int f = LCA(a,b);
long long ans = abs(dist[a] - dist[f]) + abs(dist[b] - dist[f]);
cout << ans << endl;
}
// printf("\n");
}
int main()
{
// freopen("in.in","r",stdin);
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
Max_step = lgN;
deal_init();
deal_pre();
work();
}
return 0;
}