1.倍增优化LCA
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
vector<int>G[maxn];
int root;
int V;
int parent[10][maxn];
int depth[maxn];
void dfs(int v,int p,int d){
parent[0][v] = p;
depth[v] = d;
for(int i = 0;i < G[v].size();i++){
if(G[v][i] != p) dfs(G[v][i],v,d + 1);
}
}
void init(){
dfs(root,-1,0);
for(int k = 0;k < 10;k++){
for(int v = 0;v < V;v++){
if(parent[k][v] < 0) parent[k + 1][v] = -1;
else parent[k + 1][v] = parent[k][parent[k][v]];
}
}
}
int lca(int u,int v){
if(depth[u] > depth[v]) swap(u,v);
for(int k= 0;k < 10;k++){
if((depth[v]-depth[u])>>k&1){
v = parent[k][v];
}
}
if(u == v) return u;
for(int k = 10;k >= 0;k--){
if(parent[k][u] != parent[k][v]){
u = parent[k][u];
v = parent[k][v];
}
}
return parent[0][u];
}
int main(){
return 0;
}
2.基于欧拉序 + RMQ
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
int T,n,m;
struct Edge{
int v;
int w;
int next;
}edge[maxn * 2];
int edgecount;
int head[maxn];
void add_edge(int u,int v,int w){
edge[++edgecount].v = v;
edge[edgecount].w = w;
edge[edgecount].next = head[u];
head[u] = edgecount;
}
void In(){
int u,v,k;
scanf("%d%d",&n,&m);
for(int i = 1;i < n;i++){
scanf("%d%d%d",&u,&v,&k);
add_edge(u,v,k);
add_edge(v,u,k);
}
}
void Init(){
edgecount = 0;
memset(head,-1,sizeof(head));
}
int vs[maxn * 2];
int depth[maxn * 2];
int id[maxn * 2];
void Dfs(int u,int p,int d,int &x){
id[u] = x;
vs[x] = u;
depth[x++] = d;
for(int k = head[u];k != -1;k = edge[k].next){
int v = edge[k].v;
int w = edge[k].w;
if(v != p){
Dfs(v,u,d + w,x);
vs[x] = u;
depth[x++] = d;
}
}
}
int dp[maxn * 2][20];
void RMQ_init(int n){
for(int i = 1;i <= n;i++) dp[i][0] = i;
for(int j = 1;(1 << j) <= n;j++){
for(int i = 1;i + (1 << j) - 1 <= n;i++){
int x = dp[i][j - 1];
int y = dp[i +(1 << (j - 1))][j - 1];
if(depth[x] < depth[y]) dp[i][j] = x;
else dp[i][j] = y;
}
}
}
int Query(int L,int R){
int k = log((double)(R - L + 1)) / log(2.0);
int x = dp[L][k];
int y = dp[R - (1 << k) + 1][k];
if(depth[x] < depth[y]) return x;
else return y;
}
void LCA(){
int root = 1;
int k = 1;
Dfs(root,-1,0,k);
RMQ_init(2 * n);
}
int main(){
int a,b;
scanf("%d",&T);
while(T--){
Init();
In();
LCA();
for(int i = 1;i <= m;i++){
scanf("%d%d",&a,&b);
int x = Query(min(id[a],id[b]),max(id[a],id[b]));
cout << depth[id[a]] + depth[id[b]] - 2 * depth[id[vs[x]]] << endl;
}
}
return 0;
}