题目:http://poj.org/problem?id=1330
题意:给定一个有向树,求树中两点的LCA
思路:倍增法,留个模板。这个讲的不错点这里
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const int N = 10010; const int INF = 0x3f3f3f3f; struct edge { int to, next; }g[N*2]; int cnt, head[N]; int dep[N], p[N][31]; int n, in[N]; void add_edge(int v, int u) { g[cnt].to = u, g[cnt].next = head[v], head[v] = cnt++; } void dfs(int v, int fa) { for(int i = head[v]; i != -1; i = g[i].next) { int u = g[i].to; if(u == fa) continue; if(! dep[u]) dep[u] = dep[v] + 1, p[u][0] = v, dfs(u, v); } } void init() { for(int j = 1; (1<<j) <= n; j++) for(int i = 1; i <= n; i++) p[i][j] = p[p[i][j-1]][j-1]; } int LCA(int v, int u) { if(dep[v] < dep[u]) swap(v, u); int d = dep[v] - dep[u]; for(int i = 0; (d>>i) != 0; i++) if((d>>i) & 1) v = p[v][i]; if(v == u) return v; for(int i = 20; i >= 0; i--) if(p[v][i] != p[u][i]) v = p[v][i], u = p[u][i]; return p[v][0]; } int main() { int t, a, b; scanf("%d", &t); while(t--) { scanf("%d", &n); cnt = 0; memset(head, -1, sizeof head); memset(in, 0, sizeof in); for(int i = 1; i < n; i++) scanf("%d%d", &a, &b), add_edge(a, b), in[b]++; memset(dep, 0, sizeof dep); int root; for(int i = 1; i <= n; i++) if(in[i] == 0) root = i; dep[root] = 1; dfs(root, -1); init(); scanf("%d%d", &a, &b); printf("%d\n", LCA(a, b)); } return 0; }