https://vjudge.net/problem/POJ-1330
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MAXV = 10005;
const int DEG = 20;
struct Edge {
int to, nxt;
}edge[MAXV << 1];
int head[MAXV], tol;
int fa[MAXV][DEG], deg[MAXV];
void addedge(int u, int v) {
++tol;
edge[tol].to = v; edge[tol].nxt = head[u];
head[u] = tol;
}
void bfs(int root) {
queue<int> que;
que.push(root);
deg[root] = 0;
fa[root][0] = root;
while (!que.empty()) {
int cur = que.front();
que.pop();
for (int i = 1; i < DEG; ++i)
fa[cur][i] = fa[fa[cur][i - 1]][i - 1];
for (int i = head[cur]; i != -1; i = edge[i].nxt) {
int v = edge[i].to;
if (v != fa[cur][0]) {
que.push(v);
deg[v] = deg[cur] + 1;
fa[v][0] = cur;
}
}
}
}
int LCA(int x, int y) {
if (deg[x] < deg[y])
swap(x, y);
for (int det = deg[x] - deg[y], i = 0; det; det >>= 1, ++i)
if (det & 1)
x = fa[x][i];
if (x == y) return x;
for (int i = DEG - 1; i >= 0; --i)
if (fa[x][i] != fa[y][i])
x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
int main() {
int q;
scanf("%d", &q);
while (q--) {
memset(head, -1, sizeof head);
tol = 0;
int n;
bool found[MAXV];
memset(found, false, sizeof found);
scanf("%d", &n);
for (int i = 1; i < n; ++i) {
int u, v;
scanf("%d%d", &u, &v);
addedge(u, v);
found[v] = true;
}
int root;
for (int i = 1; i <= n; ++i)
if (!found[i])
root = i;
bfs(root);
int u, v;
scanf("%d%d", &u, &v);
printf("%d\n", LCA(u, v));
}
return 0;
}