题意:给定一棵树,询问两个节点的最近公共祖先。
输入:第一行T,表示测试组数。
每组测试数据包含一个n,表示节点数目,下面n-1行是连接的边,最后一行是询问
输出:共T行,代表每组的测试结果
/* 倍增LCA 注意这是树,所以边是单向的,深搜的时候从根节点开始搜 */ #include<cstdio> #include<iostream> #include<cstring> #define M 10010 #define S 20 using namespace std; int head[M],deep[M],fa[M][S+5],in[M],num,n; struct node { int u,v,pre; };node e[M*2]; void add(int x,int y) { ++num; e[num].u=x; e[num].v=y; e[num].pre=head[x]; head[x]=num; } void dfs(int now,int from,int c) { fa[now][0]=from;deep[now]=c; for(int i=head[now];i;i=e[i].pre) if(e[i].v!=from) dfs(e[i].v,now,c+1); } void get_fa() { for(int j=1;j<=S;j++) for(int i=1;i<=n;i++) fa[i][j]=fa[fa[i][j-1]][j-1]; } int get_same(int a,int t) { for(int i=0;i<=S;i++) if(t&(1<<i)) a=fa[a][i]; return a; } int LCA(int a,int b) { if(deep[a]<deep[b])swap(a,b); a=get_same(a,deep[a]-deep[b]); if(a==b)return a; for(int i=S;i>=0;i--) if(fa[a][i]!=fa[b][i]) { a=fa[a][i]; b=fa[b][i]; } return fa[a][0]; } void init() { scanf("%d",&n); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); in[y]++; add(x,y); } int p; for(int i=1;i<=n;i++) if(!in[i]) { p=i; break; } dfs(p,p,0); get_fa(); int a,b; scanf("%d%d",&a,&b); printf("%d ",LCA(a,b)); } int main() { int T; scanf("%d",&T); while(T--) { memset(e,0,sizeof(e)); memset(head,0,sizeof(head)); memset(deep,0,sizeof(deep)); memset(fa,0,sizeof(fa)); memset(in,0,sizeof(in)); num=0; init(); } return 0; }