一:Tarjan离线求LCA
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 100080
#define maxm 200160
int first[maxn],dis[maxn],vis[maxn],fa[maxn];
int firstq[maxn];
int vv[maxm],nxt[maxm],ww[maxm];
int vvq[maxm],nxtq[maxm],ansq[maxm];
int e,eq;
void init()
{
e = eq = 0;
memset(vis,0,sizeof(vis));
memset(first,-1,sizeof(first));
memset(firstq,-1,sizeof(firstq));
}
int find(int x)
{
if(x == fa[x]) return x;
return fa[x] = find(fa[x]);
}
void addedge(int u,int v,int w)
{
vv[e] = v; ww[e] = w; nxt[e] = first[u]; first[u] = e++;
vv[e] = u; ww[e] = w; nxt[e] = first[v]; first[v] = e++;
}
void addquery(int u,int v)
{
vvq[eq] = v; nxtq[eq] = firstq[u]; firstq[u] = eq++;
vvq[eq] = u; nxtq[eq] = firstq[v]; firstq[v] = eq++;
}
void Tarjan(int u,int pre)
{
fa[u] = u;
for(int i = first[u];i != -1;i = nxt[i])
{
int v = vv[i];
if(v == pre) continue;
dis[v] = dis[u] + ww[i];
Tarjan(v,u);
fa[v] = u;
}
vis[u] = 1;
for(int i = firstq[u];i != -1;i = nxtq[i])
{
int v = vvq[i];
if(vis[v]) ansq[i] = find(v);
}
}
int main()
{
freopen("in.txt","r",stdin);
int n;
while(scanf("%d",&n)!=EOF)
{
init();
for(int i = 1;i < n;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
}
int q;
scanf("%d",&q);
for(int i = 1;i <= q;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addquery(u,v);
}
dis[1] = 0;
Tarjan(1,-1);
for(int i = 0;i < eq;i+=2)
{
if(ansq[i] == 0) ansq[i] = ansq[i^1];
printf("%d\n",ansq[i]);
}
}
return 0;
}
二:预处理2的若干次幂祖先。先将u和v中深度大的跳到深度一样。然后一起往上跳。
PS:这里写的不是很好。稍后来改。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 100080
#define maxm 200160
int first[maxn],dis[maxn],dep[maxn],fa[maxn][20];
int vv[maxm],ww[maxm],nxt[maxm];
int e;
void init()
{
e = 0;
memset(first,-1,sizeof(first));
memset(dep,-1,sizeof(dep));
memset(fa,-1,sizeof(fa));
}
void addedge(int u,int v,int w)
{
vv[e] = v; ww[e] = w; nxt[e] = first[u]; first[u] = e++;
vv[e] = u; ww[e] = w; nxt[e] = first[v]; first[v] = e++;
}
void dfs(int u,int pre)
{
fa[u][0] = pre;
//祖先初始化
int pos = 0;
while(fa[fa[u][pos]][pos] != -1)
{
pos++;
fa[u][pos] = fa[fa[u][pos-1]][pos-1];
}
for(int i = first[u];i != -1;i = nxt[i])
{
int v = vv[i];
if(v == pre) continue;
dep[v] = dep[u]+1;
dis[v] = dis[u] + ww[i];
dfs(v,u);
}
}
int lca(int u,int v)
{
if(dep[u] < dep[v])
swap(u,v);
while(dep[u] > dep[v])
{
int pos = 0;
while(fa[u][pos] != -1 && dep[fa[u][pos]] >= dep[v])
pos++;
u = fa[u][pos-1];
}
//到这里的时候就在同一层了
while(u != v)
{
int pos = 1;
while(fa[u][pos] != fa[v][pos])
pos++;
u = fa[u][pos-1],v = fa[v][pos-1];
}
return u;
}
int main()
{
freopen("in.txt","r",stdin);
int n;
while(scanf("%d",&n)!=EOF)
{
init();
for(int i = 1;i < n;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
}
int q;
scanf("%d",&q);
dis[1] = 0;dep[1] = 0;
dfs(1,-1);
for(int i = 1;i <= q;i++)
{
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",lca(u,v));
}
}
}