lca的离线操作:这篇博客写的很好 https://www.cnblogs.com/JVxie/p/4854719.html。。
我实现的代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=80010;
struct node
{
int v,next,w;
}edge[maxn*2];
int n;
int head[maxn],dis[maxn],cnt,pre[maxn],ancestor[maxn],vis[maxn],answer[maxn];
int ans[maxn];
void init()
{
memset(head,-1,sizeof(head));
memset(dis,0,sizeof(dis));
for(int i=1;i<=n;i++)
{
pre[i]=i;
}
cnt=0;
memset(vis,0,sizeof(vis));
memset(ancestor,0,sizeof(ancestor));
}
int find(int x)
{
int r=x;
while(r!=pre[r])
r=pre[r];
int i=x,j;
while(i!=r)
{
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
void bing(int x,int y)
{
int tx=find(x);
int ty=find(y);
if(tx!=ty)
{
pre[tx]=ty;
}
}
void add_edge(int u,int v,int w)
{
edge[cnt].v=v;
edge[cnt].next=head[u];
edge[cnt].w=w;
head[u]=cnt++;
}
struct query
{
int v,index,next,u;
}query_edge[maxn];
int h[maxn],cc=0;
void initt()
{
memset(h,-1,sizeof(h));
cc=0;
}
void add_query(int u,int v,int index)
{
query_edge[cc].v=v;
query_edge[cc].u=u;
query_edge[cc].next=h[u];
query_edge[cc].index=index;
h[u]=cc++;
}
void lca(int u)
{
vis[u]=1;
ancestor[u]=u;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(vis[v])
continue;
dis[v]=dis[u]+edge[i].w;
lca(v);
bing(u,v);
ancestor[find(u)]=u;
}
for(int i=h[u];i!=-1;i=query_edge[i].next)
{
int v=query_edge[i].v;
if(vis[v])
{
answer[query_edge[i].index]=dis[u]+dis[v]-dis[ancestor[find(v)]]*2;
}
}
}
int main ()
{
int t;
scanf("%d",&t);
while(t--)
{
int m;
scanf("%d%d",&n,&m);
init();
for(int i=1;i<n;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
add_edge(v,u,w);
}
initt();
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add_query(u,v,i);
add_query(v,u,i);
}
int num=0;
int flag[maxn];
int root;
for(int i = 1;i <= n;i++)
if(!flag[i])
{
root = i;
break;
}
lca(root);
for(int i=1;i<=m;i++)
{
printf("%d\n",answer[i]);
}
}
}