倍增
用\(f[cur][i]\)表示\(cur\)的第\(\ 2^i\)個祖先
\(f[cur][i] = f[f[cur][i-1]][i-1]\)
因爲\(\ 2{i-1}+2{i-1}=2^i\)
調試記錄
\(f[cur][0] = fa\)
#include <cstdio>
#include <algorithm>
#define maxn 500005
#define logn 25
using namespace std;
struct node{
int to, nxt;
}e[maxn << 1];
int head[maxn], tot = 0;
void addedge(int u, int v){
e[++tot].to = v, e[tot].nxt = head[u];
head[u] = tot;
}
int n, m, root;
int dep[maxn], f[maxn][logn + 5];
void dfs(int cur, int fa){
dep[cur] = dep[fa] + 1;
f[cur][0] = fa;
for (int i = 1; (1 << i) <= dep[cur]; i++)
f[cur][i] = f[f[cur][i - 1]][i - 1];
for (int i = head[cur]; i; i = e[i].nxt){
if (e[i].to != fa) dfs(e[i].to, cur);
}
}
int LCA(int u, int v){
if (dep[u] > dep[v]) swap(u, v);
for (int i = logn; i >= 0; i--)
if (dep[u] <= dep[v] - (1 << i)) v = f[v][i];
if (u == v) return u;
for (int i = logn; i >= 0; i--)
if (f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];
return f[u][0];
}
int main(){
scanf("%d%d%d", &n, &m, &root);
for (int u, v, i = 1; i < n; i++){
scanf("%d%d", &u, &v);
addedge(u, v), addedge(v, u);
}
dfs(root, 0);
while (m--){ int u, v;
scanf("%d%d", &u, &v);
printf("%d\n", LCA(u, v));
}
return 0;
}
Tarjan
題解
#include <cstdio>
#define maxn 500005
using namespace std;
struct node_edge{
int next, to, LCA;
}e[maxn * 2], q[maxn * 2];
int etot = 0, qtot = 1, efirst[maxn], qfirst[maxn], n, m, root;
int f[maxn];
int GetFather(int x){
if (f[x] == x) return x;
else return (f[x] = GetFather(f[x]));
}
void eAddEdge(int x, int y){
etot++;
e[etot].to = y;
e[etot].next = efirst[x];
efirst[x] = etot;
}
void qAddEdge(int x, int y){
qtot++;
q[qtot].to = y;
q[qtot].next = qfirst[x];
qfirst[x] = qtot;
}
bool vis[maxn];
void dfs(int x){
vis[f[x] = x] = true;
for (int i = efirst[x]; i; i = e[i].next){
if (!vis[e[i].to]){
dfs(e[i].to);
f[e[i].to] = x;
}
}
for (int i = qfirst[x]; i; i = q[i].next){
if (vis[q[i].to]) q[i^1].LCA = q[i].LCA = GetFather(q[i].to);
}
}
int main(){
scanf("%d%d%d", &n, &m, &root);
for (int a, b, i = 1; i < n; i++){
scanf("%d%d", &a, &b);
eAddEdge(a, b); eAddEdge(b, a);
}
for (int a, b, i = 1; i <= m; i++){
scanf("%d%d", &a, &b);
qAddEdge(a, b); qAddEdge(b, a);
}
dfs(root);
for (int i = 1; i <= m; i++) printf("%d\n", q[i * 2].LCA);
return 0;
}