最近公共祖先的经典问题。
(1)dfs暴力标记查找
(2)线段树
(3)倍增算法
(4)Tarian算法。
这些我慢慢补充,自己也在学习这个算法。
这道题数据量比较小,询问每组只有一个,所以我采用的是将其中一个数的祖先不断向上查找,并且做了vis标记。然后对于另一个进行的查找操作,
当访问的节点正好是已经做了vis标记的,那么这个就是lca,输出即可。
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
int fa[10002];
int vis[10002];
void dfs(int k)//向上查找直到根为止
{
if(fa[k]==k)
{
vis[k]=1;
return ;
}
else
{
vis[fa[k]]=1;
dfs(fa[k]);
}
}
int main()
{
int T,n,a,b,ansa,ansb;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
fa[i]=i;
memset(vis,0,sizeof(vis));
for(int i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
fa[b]=a;
}
scanf("%d%d",&ansa,&ansb);
vis[ansa]=1;//不要忘记标记起始位置
dfs(ansa);
int ans=ansb;
while(!vis[ansb])
{
ansb=fa[ansb];
ans=ansb;
}
printf("%d\n",ans);
}
}