倍增求LCA:
1.先转化成有根树。
2.dfs求出每个点的深度
3.初始化anc数组
4.倍增查询
#include<bits/stdc++.h>
using namespace std;
const int maxn=4e4+7;
int anc[maxn][20],deep[maxn],d[maxn],k;
int rt,n;
struct Edge
{
int v,d;
Edge(){}
Edge(int _v,int _d):v(_v),d(_d){}
};
vector<Edge> adj[maxn];
void dfs(int u,int pre,int deep,int dis)
{
anc[u][0]=pre;
d[u]=dis;
::deep[u]=deep;
for(int i=0;i<adj[u].size();i++)
{
int v=adj[u][i].v;
if(v==pre) continue;
dfs(v,u,deep+1,dis+adj[u][i].d);
}
}
void init()
{
for(int j=1;(1<<j)<n;j++)
{
k=j;
for(int i=1;i<=n;i++)
{
anc[i][j]=-1;
int p=anc[i][j-1];
if(p==-1) continue;
anc[i][j]=anc[p][j-1];
}
}
}
int lca(int u,int v)
{
if(deep[u]<deep[v]) swap(u,v);
for(int i=k;i>=0;i--)
if(deep[u]-(1<<i)>=deep[v])
u=anc[u][i];
if(u==v) return u;
for(int i=k;i>=0;i--)
if(anc[u][i]!=anc[v][i])
{
u=anc[u][i];
v=anc[v][i];
}
return anc[u][0];
}
int main()
{
ios::sync_with_stdio(false);
int T;
cin>>T;
while(T--)
{
int m,u,v,d;
cin>>n>>m;
for(int i=1;i<=n;i++) adj[i].clear();
for(int i=1;i<n;i++)
{
cin>>u>>v>>d;
adj[u].push_back(Edge(v,d));
adj[v].push_back(Edge(u,d));
}
rt=1;
dfs(rt,-1,1,0);
init();
while(m--)
{
cin>>u>>v;
int fa=lca(u,v);
cout << ::d[u]-::d[fa]+::d[v]-::d[fa] << endl;
}
}
return 0;
}
dfs序+ST表:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
struct Node
{
int v,d;
};
vector<Node> adj[N];
int n;
namespace LCA
{
int ord[N<<1],d[N<<1],fir[N],dp[N<<1][20],mm[N<<1],m=0;
void dfs_lca(int u,int p,int deep)
{
ord[++m]=u;
d[m]=deep;
fir[u]=m;
for(int i=0;i<adj[u].size();++i)
{
int v=adj[u][i].v;
if(v==p) continue;
dfs_lca(v,u,deep+1);
ord[++m]=u;
d[m]=deep;
}
}
void init_RMQ()
{
mm[0] = -1;
for(int i=1;i<=m;++i)
{
mm[i]= ((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
dp[i][0]=i;
}
for(int j=1;j<=mm[m];++j)
for(int i=1;i+(1<<j)-1<=m;++i)
{
int x=dp[i][j-1],y=dp[i+(1<<(j-1))][j-1];
dp[i][j]=d[x]<d[y]?x:y;
}
}
int lca(int u,int v)
{
u=fir[u],v=fir[v];
if(u>v) swap(u,v);
int k=mm[v-u+1];
int x=dp[u][k],y=dp[v-(1<<k)+1][k];
return d[x]<d[y]?ord[x]:ord[y];
}
void init(int u)
{
m=0;
dfs_lca(u,0,0);
init_RMQ();
}
}
int d[N];
void dfs(int u,int p)
{
for(auto e : adj[u])
{
int v=e.v,c=e.d;
if(v==p) continue;
d[v]=d[u]+c;
dfs(v,u);
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int q;
scanf ("%d%d",&n,&q);
for(int i=1;i<=n;++i) adj[i].clear();
for(int i=1;i<n;++i)
{
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
adj[u].push_back({v,c});
adj[v].push_back({u,c});
}
d[1]=0;
LCA::init(1);
dfs(1,0);
while(q--)
{
int u,v;
scanf("%d%d",&u,&v);
int lca=LCA::lca(u,v);
printf("%d\n",d[u]+d[v]-2*d[lca]);
}
}
return 0;
}