LCA 在线倍增
倍增思想
倍增st表
在线倍增LCA代码
#include<iostream>
using namespace std;
const int mxn = 5e5 + 10;
struct Edge
{
int v, next;
} edge[mxn * 2];
int head[mxn], num = 0;
void Add(int u, int v)
{
edge[++ num] = (Edge){ v, head[u] };
head[u] = num;
}
int f[mxn][30], dep[mxn];
void dfs(int u, int pre)
{
f[u][0] = pre;
dep[u] = dep[pre] + 1;
for(int i = 1; (1 << i) <= dep[u]; i ++)
f[u][i] = f[f[u][i - 1]][i - 1];
for(int i = head[u]; i; i = edge[i].next)
{
int v = edge[i].v;
if(v != pre)
dfs(v, u);
}
}
int lca(int a, int b)
{
if(dep[a] < dep[b]) swap(a, b);
for(int i = 20; i >= 0; i --)
if(dep[f[a][i]] >= dep[b])
a = f[a][i];
if(a == b) return a;
for(int i = 20; i >= 0; i --)
{
if(f[a][i] != f[b][i])
{
a = f[a][i];
b = f[b][i];
}
}
return f[a][0];
}
int main()
{
int n, m, s;
scanf("%d %d %d", &n, &m, &s);
int u, v;
for(int i = 1; i < n; i ++)
{
scanf("%d %d", &u, &v);
Add(u, v);
Add(v, u);
}
dfs(s, 0);
while(m --)
{
scanf("%d %d", &u, &v);
printf("%d\n", lca(u, v));
}
return 0;
}
LCA离线Tarjan
LCA离线Trajin代码(很大几率存在错误,待修改)
#include<iostream>
#include<cstring>
using namespace std;
const int mxn = 1e5;
struct Edge
{
int u, v, w, next, lca;
} e1[mxn], e2[mxn];
int h1[mxn], h2[mxn];
int t1, t2;
int vis[mxn], dis[mxn];
void Add(int u, int v, int w, int & t, Edge e[], int h[])
{
e[++ t] = (Edge){ u, v, w, h[u] }; h[u] = t;
}
int f[mxn];
int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
void join(int x, int y)
{
int fx = find(x);
int fy = find(y);
if(fx != fy)
f[fx] = fy;
}
void Tarjan_Lca(int u, int w)
{
f[u] = u;
dis[u] = w;
vis[u] = 1;
for(int i = h1[u]; i; i = e1[i].next)
{
Tarjan_Lca(u, w + e1[i].w);
f[e1[i].v] = u;
}
for(int i = h2[u]; i; i = e2[i].next)
{
int v = e2[i].v;
if(vis[v])
{
e2[i].lca = find(v);
e2[i].w = dis[u] + dis[v] - dis[e2[i].lca] * 2;
}
}
}
void init(int n)
{
t1 = t2 = 0;
for(int i = 1; i <= n; i ++) f[i] = i, vis[i] = 0;
}
int main()
{
int n, m, s;
scanf("%d %d %d", &n, &m, &s);
init(n);
int u, v, w;
for(int i = 1; i < n; i ++)
{
scanf("%d %d %d", &u, &v, &w);
Add(u, v, w, t1, e1, h1);
}
for(int i = 1; i <= m; i ++)
{
scanf("%d %d", &u, &v);
Add(u, v, -1, t2, e2, h2);
}
Tarjan_Lca(s, 0);
for(int i = 1; i <= m; i ++)
printf("%d %d\n", e2[i].lca, e2[i].w);
return 0;
}