最近公共祖先的经典问题。
(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); } }