给出一棵树的父子关系,求指定的两个结点的最近公共祖先。
关于最近公共祖先(LCA)的资料如下:
由于存在父子关系,因此建图的时候建立的是有向边,在进行dfs前,需要找到根节点(入度为0),从该结点开始DFS。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
#define maxn 40005
#define maxm 1000005
vector<int> G[maxn],Q[maxn];
bool vis[maxn];
int fa[maxn],ans[205];
int Find(int x)
{
if(fa[x]==x) return x;
return fa[x]=Find(fa[x]);
}
void Union(int x,int y)
{
x=Find(x);
y=Find(y);
if(x==y) return;
fa[y]=x;
}
bool flag=0;
void dfs(int u)
{
vis[u]=1;
for(int i=0;i<(int)G[u].size();++i)
{
int v=G[u][i];
if(vis[v]) continue;
dfs(v);
Union(u,v);
}
if(flag) return;
for(int i=0;i<(int)Q[u].size();++i)
{
int v=Q[u][i];
if(!vis[v]) continue;
flag=1;
printf("%d\n",Find(v));
return;
}
}
int in[maxn];
int main()
{
int n,i,T,u,v;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
flag=0;
for(i=0;i<=n;++i){
G[i].clear();
Q[i].clear();
fa[i]=i;
vis[i]=0;
in[i]=0;
}
for(i=0;i<n-1;++i)
{
scanf("%d%d",&u,&v);
G[u].push_back(v);
++in[v];
}
scanf("%d%d",&u,&v);
Q[u].push_back(v);
Q[v].push_back(u);
for(i=1;i<=n;++i)
if(in[i]==0) {dfs(i);break;}
}
return 0;
}