题意:
一道很裸的LCA题
以一个点建树,两点间最短的距离可以转化为求两近公共祖先,最短距离,depth[x]-depth[l]+depth[y]-depth[l]
在dfs求得每个点到顶点距离
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=4e4+5;
const int maxbit=15;
struct edge
{
int to;
int val;
};
int father[maxn][maxbit];
int depth[maxn];
int dis[maxn];vector<edge>G[maxn];
int lg[maxn];
void dfs(int nowp,int fa)
{
depth[nowp]=depth[fa]+1;
father[nowp][0]=fa;
for(int j=1;j<=lg[depth[nowp]];j++)
father[nowp][j]=father[father[nowp][j-1]][j-1];
for(int i=0;i<G[nowp].size();i++)
{
edge e=G[nowp][i];
if(e.to!=fa)
{
dis[e.to]=dis[nowp]+e.val;//算距离
dfs(e.to,nowp);
}
}
}
int lca(int u,int v)
{
if(depth[u]<depth[v])
swap(u,v);
while(depth[u]!=depth[v])
u=father[u][lg[depth[u]-depth[v]]];
if(u==v)return u;
for(int j=lg[depth[u]];j>=0;j--)
{
if(father[u][j]!=father[v][j])
{
u=father[u][j];
v=father[v][j];
}
}
return father[u][0];
}
int main()
{
lg[0]=-1;
for(int i=1;i<maxn;i++)
lg[i]=lg[i>>1]+1;
int t;
scanf("%d",&t);
while(t--)
{
memset(father,0,sizeof father);
memset(depth,0,sizeof depth);
memset(dis,0,sizeof dis);
int n,m;
scanf("%d%d",&n,&m);
int x,y,k;
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&k);
G[x].push_back({y,k});
G[y].push_back({x,k});
}
dfs(1,0);
while(m--)
{
scanf("%d%d",&x,&y);
int l=lca(x,y);
printf("%d\n",(dis[x]-dis[l])+(dis[y]-dis[l]));
}
}
return 0;
}