目录:
分析:
这题还是十分水的,算一道LCA的入门模版,也没啥需要特别注意的,但是我们不能将1定为根,需要在入度为0的点中任意选一个进行LCA
思路:
1.边读入,边建邻接表
2.找到第一个入度为0的点
3.dfs求点深度
4.常规LCA
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
struct edge{
int to,next;
}e[20001];
int ls[20001],f[20001][21],dep[20001];
void dfs(int fa,int now)
{
f[now][0]=fa;
dep[now]=dep[fa]+1;
for(int i=ls[now];i;i=e[i].next)
if(!dep[e[i].to]) dfs(now,e[i].to);
}
int LAC(int l,int r)
{
if(dep[l]<dep[r]) swap(l,r);
for(int i=20;i>=0;i--)
if(dep[r]<=dep[f[l][i]])
l=f[l][i];
if(l==r) return l;
for(int i=20;i>=0;i--)
if(f[l][i]!=f[r][i])
{
l=f[l][i];
r=f[r][i];
}
return f[l][0];
}
int r[20001];
int main()
{
int w=read();int king;
for(int k=1;k<=w;k++)
{
memset(f,0,sizeof(f));//初始化
memset(ls,0,sizeof(ls));
memset(dep,0,sizeof(dep));
memset(r,0,sizeof(r));
int n=read(),l=0;
int a,b;
for(int i=2;i<=n;i++)
{
a=read();b=read();
e[++l]=(edge){b,ls[a]};
ls[a]=l;
r[b]++;
}
for(int i=1;i<=n;i++) if(r[i]==0) {king=i;break;}
dfs(0,king);
for(int j=1;j<=20;j++)
for (int i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1];
a=read();
b=read();
printf("%d\n",LAC(b,a));
}
return 0;
}