图论 - 树论 - LCA
图论 - 树论 - LCA
朴素 题目链接:http://poj.org/problem?id=1330
倍增 、 树剖 题目链接: https://www.luogu.org/problem/P3379
朴素代码:
//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 10010;
int T, n, vis[N];
int tot, head[N], nxt[N << 1], to[N << 1];
void add(int x, int y) {
to[ ++ tot] = y;
nxt[tot] = head[x];
head[x] = tot;
}
int fa[N], dep[N];
void dfs(int now, int pre) {
dep[now] = dep[pre] + 1;
fa[now] = pre;
for (int i = head[now]; i; i = nxt[i]) {
if (to[i] == pre) {
continue ;
}
dfs(to[i], now);
}
}
int LCA(int x, int y) {
if (dep[x] < dep[y]) {
swap(x, y);
}
while (dep[x] > dep[y]) {
x = fa[x];
}
while (x != y) {
x = fa[x], y = fa[y];
}
return x;
}
void init() {
tot = 0;
memset(head, 0, sizeof head);
memset(vis, 0, sizeof vis);
memset(dep, 0, sizeof dep);
}
int main() {
scanf("%d", &T);
while (T -- ) {
init();
tot = 0;
scanf("%d", &n);
for (int i = 1; i <= n - 1; i ++ ) {
int a, b;
scanf("%d%d", &a, &b);
vis[b] = 1;
add(a, b);
}
int root;
for (int i = 1; i <= n; i ++ ) {
if (! vis[i]) {
root = i;
break ;
}
}
dfs(root, root);
int qa, qb;
scanf("%d%d", &qa, &qb);
printf("%d\n", LCA(qa, qb));
}
return 0;
}
倍增LCA:
// #include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 500500;
int n, m, s;
int tot, to[N << 1], nxt[N << 1], head[N];
void add(int x, int y) {
to[ ++ tot] = y;
nxt[tot] = head[x];
head[x] = tot;
}
int fa[N][25], dep[N];
void dfs(int pos, int pre) {
fa[pos][0] = pre;
dep[pos] = dep[pre] + 1;
for (int i = 1; i <= 20; i ++ ) {
if ((1 << i) >= dep[pos]) {
break ;
}
fa[pos][i] = fa[fa[pos][i - 1]][i - 1];
}
for (int i = head[pos]; i; i = nxt[i]) {
if (to[i] != pre) {
dfs(to[i], pos);
}
}
}
int lca(int x, int y) {
if (dep[x] < dep[y]) {
swap(x, y);
}
for (int i = 20; i >= 0; i -- ) {
if (dep[fa[x][i]] >= dep[y]) {
x = fa[x][i];
}
}
if (x == y) {
return x;
}
for (int i = 20; i >= 0; i -- ) {
if (fa[x][i] != fa[y][i]) {
x = fa[x][i];
y = fa[y][i];
}
}
return fa[x][0];
}
int main() {
scanf("%d%d%d", &n, &m, &s);
for (int i = 1; i <= n - 1; i ++ ) {
int a, b;
scanf("%d%d", &a, &b);
add(a, b);
add(b, a);
}
dfs(s, 0);
for (int i = 1; i <= m; i ++ ) {
int a, b;
scanf("%d%d", &a, &b);
printf("%d\n", lca(a, b));
}
return 0;
}
树剖LCA:
#include <bits/stdc++.h>
using namespace std;
const int N = 500010;
int n, m, s;
int tot, head[N], to[N << 1], nxt[N << 1];
int dep[N], siz[N], fa[N], son[N], top[N];
void add(int x, int y) {
to[ ++ tot] = y;
nxt[tot] = head[x];
head[x] = tot;
}
void dfs1(int x) {
dep[x] = dep[fa[x]] + 1;
siz[x] = 1;
for (int i = head[x]; i; i = nxt[i]) {
if (to[i] == fa[x]) {
continue ;
}
fa[to[i]] = x;
dfs1(to[i]);
siz[x] += siz[to[i]];
if (! son[x] || siz[son[x]] < siz[to[i]]) {
son[x] = to[i];
}
}
}
void dfs2(int x, int fir) {
top[x] = fir;
if (son[x]) {
dfs2(son[x], fir);
}
for (int i = head[x]; i; i = nxt[i]) {
int v = to[i];
if (v == fa[x] || v == son[x]) {
continue ;
}
dfs2(v, v);
}
}
int LCA(int x, int y) {
while (top[x] != top[y]) {
if (dep[top[x]] >= dep[top[y]]) {
x = fa[top[x]];
}
else {
y = fa[top[y]];
}
}
if (dep[x] > dep[y]) {
return y;
}
else {
return x;
}
}
int main() {
scanf("%d%d%d", &n, &m, &s);
for (int i = 1; i <= n - 1; i ++ ) {
int a, b;
scanf("%d%d", &a, &b);
add(a, b);
add(b, a);
}
dfs1(s);
dfs2(s, s);
for (int i = 1; i <= m; i ++ ) {
int a, b;
scanf("%d%d", &a, &b);
printf("%d\n", LCA(a, b));
}
return 0;
}