题意
求一棵树上的某两个节点的最近公共祖先。
思路
这是tarjan算法的例题,所以我这里用的是tarjan算法。
代码
#include<cstdio>
#include<cstring>
using namespace std;
int f1,f2,p,q,t,n,m,x,y,root,tot,head[10001],v[10001],fa[10001];
struct node{
int x,y,next;
}edge[10001];
int find(int x)
{
return x==fa[x]?x:fa[x]=find(fa[x]);
}
void insert(int x,int y)
{
f1=find(x);f2=find(y);
if (f1!=f2) fa[f1]=f2;
}
void dfs(int x)
{
v[x]=1;
if (x==p&&v[q]||x==q&&v[p])//如果两个点都搜过了那我们就能得出答案
if (x==p) printf("%d\n",find(q));
else printf("%d\n",find(p));
for (int i=head[x];i;i=edge[i].next)//继续遍历
{
dfs(edge[i].y);
insert(edge[i].y,x);//合并并查集
}
}
int main()
{
scanf("%d",&t);
for (int i=1;i<=t;i++)
{
scanf("%d",&n);
memset(head,0,sizeof(head));
memset(v,0,sizeof(v));
for (int i=1;i<n;i++)//建邻接表
{
scanf("%d%d",&edge[i].x,&edge[i].y);
edge[i].next=head[edge[i].x];
head[edge[i].x]=i;
v[edge[i].y]=1;
}
scanf("%d%d",&p,&q);
for (int i=1;i<=n;i++)
if (v[i]==0) {root=i;break;}//找到入度为0的节点作为根去寻找
for (int i=1;i<=n;i++)
fa[i]=i;//并查集的初始化
memset(v,0,sizeof(v));
dfs(root);//从root开始搜索
}
}