#include<iostream> #include<queue> #include<vector> #include<cstdio> #include<cstring> using namespace std; const int maxn = 10086; int num[maxn]; int bin[30]; int deep[maxn]; int q1,q2; int fa[maxn][30]; vector<int>u[maxn]; int root; void get_f() { for(int i=0;i<=20;i++){ bin[i]=(1<<i); } } void build()//输入,建树,并找到根节点 { int n; int x,y; scanf("%d",&n); for(int i=1;i<=n-1;i++){ scanf("%d%d",&x,&y); u[x].push_back(y); num[y]++; } for(int i=1;i<=n;i++){ if(!num[i]){ root=i; } } scanf("%d%d",&q1,&q2); } void init()//初始化 { memset(fa,0,sizeof(fa)); memset(deep,0,sizeof(deep)); memset(num,0,sizeof(num)); for(int i=0;i<maxn;i++){ u[i].clear(); } } void bfs()//找出每个节点的深度,填写fa数组 { queue<int>q; int cur; q.push(root); deep[root]=1; while(!q.empty()){ cur=q.front();q.pop(); for(int i=1;i<20;i++){ if(deep[cur]<bin[i]){break;} fa[cur][i]=fa[fa[cur][i-1]][i-1];//现在这个节点的第2^i个爸爸 //就是他的2^(i-1)个爸爸的第2^(i-1)个爸爸 } int siz=u[cur].size(); for(int i=0;i<siz;i++){ q.push(u[cur][i]); fa[u[cur][i]][0]=cur;//亲爸爸 deep[u[cur][i]]=deep[cur]+1; } } } int lca() { int x=q1,y=q2; if(deep[x]<deep[y]){swap(x,y);} int t=deep[x]-deep[y]; for(int i=0;i<20;i++){ if(t&bin[i]){x=fa[x][i];} }//化为相同深度 for(int i=19;i>=0;i--){ if(fa[x][i]^fa[y][i]){ x=fa[x][i]; y=fa[y][i]; } }//如果第2^i个父节点不同,一同向上移动 if(x==y){return x;} return fa[x][0]; } int main() { int T; get_f(); scanf("%d",&T); while(T--){ init(); build(); bfs(); printf("%d ",lca()); } return 0; }
代码可以AC POJ1330