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
题意:给n个节点的树,求任意二点的距离; 假设求x,y,二点的距离 x,y的LCA为r 根节点为1(树,任意点可以做根)
画个图知道 dis(x,y)=dis(1,x)+dis(1,y)-2*dis(1,r), 不废话了,目的就是要在lon(n)求LCA
f(x,k)表示 x向根节点走 2的k次方的 祖先节点,f数组要保存 x的所有2次方节点 1,2,4,8其他不保存;
f(x,0)表示x的父亲节点 (显然,向根节点走1步) f(x,k)=0,表示x的2的k次方祖先不存在;k属于 [1,logn]
f[x][k]=f[f[x][k-1][k-1] 状态转移方程 假设k==2 x向根节点走4步 = x向跟节点走2步的那个节点 再向根节点走2步
因为 f[x][k-1] 是x的祖先,那么 f[x][k-1]肯定被更新过
大部分内容来自 lyd大佬的 算法竞赛进阶指南 算法竞赛进阶指南 算法竞赛进阶指南 算法竞赛进阶指南 算法竞赛进阶指南
d[i]表示i的深度, dis[i] 表示到1节点的距离
#include<bits/stdc++.h>
using namespace std;
const int len=4e4+5;
int g,tot;
int head[len*2],nex[len*2],ver[len*2],val[len*2];
void add(int u,int v,int w)//邻接表存边
{
tot++;
ver[tot]=v;val[tot]=w;
nex[tot]=head[u];head[u]=tot;
}
int d[len],dis[len];
int f[len][20];
queue<int>qu;
void bfs()
{
while(qu.size())qu.pop();
d[1]=1;
qu.push(1);
while(qu.size())
{
int u=qu.front();qu.pop();
for(int i=head[u];i;i=nex[i])
{
int v=ver[i],w=val[i];
if(!d[v])
{
dis[v]=dis[u]+w;
d[v]=d[u]+1;
f[v][0]=u;
qu.push(v);
for(int j=1;j<=g;++j)// 更新 v节点所有 的 2 次方祖先
f[v][j]=f[f[v][j-1]][j-1];
}
}
}
}
int lca(int x,int y)
{
if(d[x]>d[y])swap(x,y);//保证y的深度大于 x的深度
for(int i=g;i>=0;--i)
if(d[f[y][i]]>=d[x])y=f[y][i]; // 这个操作保证 x 和 yy 在同一深度 请画图理解
if(x==y)return x; //x和y在同一条链上
for(int i=g;i>=0;--i)
if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];//求Lca 请画图理解
return f[x][0];
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n,q;
tot=0;
memset(head,0,sizeof(head));
memset(dis,0,sizeof(dis));
memset(f,0,sizeof(f));
memset(d,0,sizeof(d));
scanf("%d%d",&n,&q);
g=int(log(n)/log(2))+1;
for(int i=1;i<n;++i)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
bfs();
while(q--)
{
int x,y;
scanf("%d%d",&x,&y);
int r=lca(x,y);
printf("%d\n",dis[x]+dis[y]-2*dis[r]);
}
}
}