题意
第一行输入T,有T组数据。
对于每组数据,给出一棵树,先输入n,然后n-1行,每行两个数a,b,表示a是b的父亲;第n行输入两个数A,B表示询问A和B的最近公共祖先。
题解
LCA模板题。
LCA倍增算法&POJ1330代码
#include <cstring> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cmath> #include <vector> using namespace std; const int N=10000+5; vector <int> son[N]; int T,n,depth[N],fa[N][17],in[N],a,b; void dfs(int prev,int rt){ depth[rt]=depth[prev]+1; fa[rt][0]=prev; for (int i=1;(1<<i)<=depth[rt];i++) fa[rt][i]=fa[fa[rt][i-1]][i-1]; for (int i=0;i<son[rt].size();i++) dfs(rt,son[rt][i]); } int LCA(int a,int b){ if (depth[a]>depth[b]) swap(a,b); for (int i=depth[b]-depth[a],j=0;i>0;i>>=1,j++) if (i&1) b=fa[b][j]; if (a==b) return a; int k; for (k=0;(1<<k)<=depth[a];k++); for (;k>=0;k--) if ((1<<k)<=depth[a]&&fa[a][k]!=fa[b][k]) a=fa[a][k],b=fa[b][k]; return fa[a][0]; } int main(){ scanf("%d",&T); while (T--){ scanf("%d",&n); for (int i=1;i<=n;i++) son[i].clear(); memset(in,0,sizeof in); for (int i=1;i<n;i++){ scanf("%d%d",&a,&b); son[a].push_back(b); in[b]++; } depth[0]=-1; int rt=0; for (int i=1;i<=n&&rt==0;i++) if (in[i]==0) rt=i; dfs(0,rt); scanf("%d%d",&a,&b); printf("%d ",LCA(a,b)); } return 0; }