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
这个题我之前,准确的说是8个月前写过,但是之前使用离线tarjan算法实现的(说实话,离线tarjan算法我也已经忘了),今天学习了倍增的LCA,说实话我不打算学的,但是最近似乎总是遇到这个东西,而且很奇怪,我在之前准备区域赛那段时间,都没有听说过lca的这种实现方法,LCA的st算法虽然也是用倍增实现,但是与此还是有区别。
代码:
#include<iostream>
#include<cstdio>
#include<stack>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cmath>
#define maxx 40005
#define maxn 16
using namespace std;
int n,m;
int head[maxx],nextt[maxx<<1],to[maxx<<1],w[maxx<<1];
int deep[maxx];
int cnt=0;
void addEdge(int x,int y,int cap)
{
to[++cnt]=y,w[cnt]=cap,nextt[cnt]=head[x],head[x]=cnt;
to[++cnt]=x,w[cnt]=cap,nextt[cnt]=head[y],head[y]=cnt;
}
int fa[maxx][maxn];
int gw[maxx][maxn];
int N;
void init()
{
memset(head,0,sizeof(head));
//memset(fa,0,sizeof(fa));
//memset(gw,0,sizeof(gw));
cnt=0;
N=floor(log2(n));
deep[1]=0;
}
void dfs(int root)
{
//cout<<"kaka"<<endl;
for(int i=1;i<=N;i++)
{
fa[root][i]=fa[fa[root][i-1]][i-1];
gw[root][i]=gw[root][i-1]+gw[fa[root][i-1]][i-1];
}
for(int i=head[root];i;i=nextt[i])
{
int v=to[i];
if(v==fa[root][0])
continue;
deep[v]=deep[root]+1;
fa[v][0]=root;
gw[v][0]=w[i];
dfs(v);
}
}
int lca(int a,int b)
{
if(deep[a]>deep[b])swap(a,b);
int ans=0;
for(int i=N;i>=0;i--)
if(deep[a]<deep[b]&&deep[fa[b][i]]>=deep[a])
ans+=gw[b][i],b=fa[b][i];
for(int j=N;j>=0;j--)
{
if(fa[a][j]!=fa[b][j])
{
ans+=gw[a][j];
ans+=gw[b][j];
a=fa[a][j];
b=fa[b][j];
}
}
if(a!=b)
{
ans+=gw[a][0];
ans+=gw[b][0];
}
return ans;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>m;
init();
int x,y,w;
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&w);
addEdge(x,y,w);
}
dfs(1);
while(m--)
{
int x,y;
cin>>x>>y;
cout<<lca(x,y)<<endl;
}
}
return 0;
}