转自:https://blog.csdn.net/Akatsuki__Itachi/article/details/81279173
关于LCA的Tarjan算法详解可看
https://blog.csdn.net/Septembre_/article/details/81355594
以下是根据算法自行写的模板代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=10010;
int flag[maxn],vis[maxn];
int father[maxn];
vector<int> v[maxn];
int Root,ans;
int x,y,n;
int Find(int x)
{
while(x!=father[x])
x=father[x];
return father[x];
}
void Union(int x,int y)
{
int fx=Find(x);
int fy=Find(y);
if(fx!=fy)
father[fy]=fx;
return;
}
void LCA(int root)
{
for(int i=0;i<v[root].size();i++)
{
int son=v[root][i];
if(vis[son]==0)
{
LCA(son);
Union(root,son);
vis[son]=1;
}
}
if(x==root&&vis[y]==1)
ans=Find(y);
if(y==root&&vis[x]==1)
ans=Find(x);
return;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(flag,0,sizeof(flag));
memset(vis,0,sizeof(vis));
scanf("%d",&n);
for(int i=0;i<=n;i++)
{
v[i].clear();
father[i]=i;
}
for(int i=1;i<n;i++)
{
scanf("%d %d",&x,&y);
v[x].push_back(y);
flag[y]++;
}
scanf("%d %d",&x,&y);
for(int i=1;i<=n;i++)
{
if(flag[i]==0)
{
Root=i;
break;
}
}
LCA(Root);
printf("%d\n",ans);
}
return 0;
}