模版参考:http://blog.csdn.net/non_cease/article/details/7426395
题目:给定一棵树,求两个结点的最近公共祖先。(最基础的LCA问题)
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn = 10006; int dp[maxn][15], father[maxn], dep[maxn]; bool hash[maxn], mark[maxn]; int n; void getDepth(int u) { //从叶节点向根求结点深度 int v = u, l = 0; while (dep[v] < 0) { v = father[v]; l++; } while (v != u) { dep[u] = l + dep[v]; u = father[u]; l--; } } //模版 void DP() { int i, j; memset (dp, -1, sizeof (dp)); for (i = 1; i <= n; i++) dp[i][0] = father[i]; for (j = 1; (1<<j) <= n; j++) for (i = 1; i <= n; i++) //if (dp[i][j-1] != -1) dp[i][j] = dp[dp[i][j-1]][j-1]; } int get_nearest_ancestor(int u, int v) { int tmp, log, i; if (dep[u] < dep[v]) { tmp = u; u = v; v = tmp; } for (log = 1; (1<<log) <= dep[u]; log++); log--; for (i = log; i >= 0; i--) if (dep[u]-(1<<i) >= dep[v]) u = dp[u][i]; if (u == v) return u; for (i = log; i >= 0; i--) if (dp[u][i] != -1 && dp[u][i] != dp[v][i]) u = dp[u][i],v = dp[v][i]; return father[u]; } int main() { int t, i, x, y; scanf ("%d", &t); while(t--) { memset(hash, false, sizeof (hash)); memset(mark, false, sizeof (mark)); memset(dep, -1, sizeof (dep)); scanf ("%d", &n); for (i = 1; i < n; i++) { scanf ("%d%d", &x, &y); father[y] = x; hash[y] = true; mark[x] = true; } for (i = 1; i <= n; i++) if (!hash[i]) break; father[i] = i; dep[i] = 0; for (i = 1; i <= n; i++) //遍历所有叶节点求结点的深度 if (!mark[i]) getDepth(i); DP(); scanf ("%d %d", &x, &y); printf("%d\n", get_nearest_ancestor(x, y)); } return 0; }