一、前人种树
博客:浅谈倍增法求LCA
二、沙场练兵
题目:POJ 1330 Nearest Common Ancestors
代码:
const int MAXN = 10010; const int DEG = 20; struct Edge { int to,next; }edge[MAXN*2]; int head[MAXN],tot; void addedge(int u,int v) { edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } void init() { tot = 0; memset(head,-1,sizeof(head)); } int fa[MAXN][DEG];//fa[i][j]表示结点i的第2^j个祖先 int deg[MAXN];//深度数组 void BFS(int root) { queue<int>que; deg[root] = 0; fa[root][0] = root; que.push(root); while(!que.empty()) { int tmp = que.front(); que.pop(); for(int i = 1;i < DEG;i++) fa[tmp][i] = fa[fa[tmp][i-1]][i-1]; for(int i = head[tmp]; i != -1;i = edge[i].next) { int v = edge[i].to; if(v == fa[tmp][0])continue; deg[v] = deg[tmp] + 1; fa[v][0] = tmp; que.push(v); } } } int LCA(int u,int v) { if(deg[u] > deg[v])swap(u,v); int hu = deg[u], hv = deg[v]; int tu = u, tv = v; for(int det = hv-hu, i = 0; det ;det>>=1, i++) if(det&1) tv = fa[tv][i]; if(tu == tv)return tu; for(int i = DEG-1; i >= 0; i--) { if(fa[tu][i] == fa[tv][i]) continue; tu = fa[tu][i]; tv = fa[tv][i]; } return fa[tu][0]; } bool flag[MAXN]; int main() { int T; int n; int u,v; scanf("%d",&T); while(T--) { scanf("%d",&n); init(); memset(flag,false,sizeof(flag)); for(int i = 1;i < n;i++) { scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); flag[v] = true; } int root; for(int i = 1;i <= n;i++) if(!flag[i]) { root = i; break; } BFS(root); scanf("%d%d",&u,&v); printf("%d\n",LCA(u,v)); } return 0; }