hdu 2586
dp[x][i]表示节点i往上走2^i次所到达的祖先,那么不难写出转移方程:
dp[x][i]=dp[dp[x][i-1]][i-1];
然后在求LCA的时候,有这样一个性质:(假设a和b深度一样)
于是求法就渐渐的现行了:
1. 把a和b移到同一深度(设deep[x]为节点x的深度),假设deep[a]<=deep[b],所以我们的目的是把b向上 移动i=(deep[b]-deep[a])层,那么,由于之前有预处理的dp数组,我们把i写成二进制形势,然后利用dp数 组来在log n的复杂度中完成;
2. 寻找a和b的LCA下一层的两个祖先。利用之前的那个性质,再利用倍增,如果a和b的第2^k个祖先不是
同一个,那么a=dp[a][k],b=dp[b][k];当然在这之前要实现确定k的最大值,从大往小处理下去。最终的
结果就是dp[a][0];
注意点:如果a和b在调节深度之后已经是同一个祖先的,那么直接返回a或者b。
//#include <bits/stdc++.h>
#include<stdio.h>
#include<string.h>
#include<string>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#include<set>
#include<stdlib.h>
#include<time.h>
#include <iomanip>
#define lowbit(x) (x&(-x))
#define inf 0x7fffffff
#define linf 0x7fffffffffffffff
#define fil(x,y) memset(x,y,sizeof(x))
#define fup(i,x,y) for(int i=(x);i<=(y);i++)
#define fdn(i,x,y) for(int i=(x);i>=(y);i--)
#define sp(x) setprecision(x)
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d%d",&n,&m)
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define sld(n) scanf("%lld",&n)
#define sldd(n,m) scanf("%lld%lld",&n,&m)
#define slddd(n,m,k) scanf("%lld%lld%lld",&n,&m,&k)
#define sf(n) scanf("%lf",&n)
#define sff(n,m) scanf("%lf%lf",&n,&m)
#define sfff(n,m,k) scanf("%lf%lf%lf",&n,&m,&k)
#define sc(n) scanf("%s",n)
#define pf(x) printf("%d\n",x)
#define pfl(x) printf("%lld\n",x)
#define pff(x) printf("%lf\n",x)
#define debug printf("!!\n");
#define N 1000005
#define M 4000009
#define pi acos(-1)
#define eps 1e-2
//cout.setf(ios::fixed);
//freopen("out.txt","w",stdout);// freopen("in.txt","r",stdin);
using namespace std;
typedef long long ll;
typedef double db;
int n,s;
struct node
{
int go,t;
};
int fa[100005],deep[100005],dp[100005][17],dis[100005];
vector<node> q[100005];
void dfs(int x,int dep)
{
deep[x]=dep;
dp[x][0]=fa[x];
for(int i=1;(1<<i)<deep[x];i++)
dp[x][i]=dp[dp[x][i-1]][i-1];
for(int i=0;i<q[x].size();i++)
{
node tp=q[x][i];
if(tp.go!=fa[x])
{
dis[tp.go]=dis[x]+tp.t;
fa[tp.go]=x;
dfs(tp.go,dep+1);
}
}
}
int lca(int a,int b)
{
if(deep[a]>deep[b]) swap(a,b);
int k=deep[b]-deep[a];
for(int i=0;i<=19;i++)
if((1<<i)&k) b=dp[b][i];
for(int i=19;i>=0;i--)
if(dp[a][i]!=dp[b][i]) a=dp[a][i],b=dp[b][i];
if(a==b) return a;
return dp[a][0];
}
int main()
{
int tt;
sd(tt);
while(tt--)
{
fil(dis,0);
fil(dp,0);
fil(deep,0);
fil(fa,0);
int n,m;
sdd(n,m);
fup(i,1,n-1)
{
int x,y,z;
sddd(x,y,z);
q[x].push_back(node{y,z});
q[y].push_back(node{x,z});
}
dfs(1,1);
while(m--)
{
int x,y;
sdd(x,y);
pf(dis[x]+dis[y]-2*dis[lca(x,y)]);
}
}
return 0;
}