题目链接:http://poj.org/problem?id=1330
最近公共祖先(LCA)
题意:求树上亮点的最近公共祖先,就是求包含这两个点的最小的子树的根节点。
离线算法(Tarjan):
就是预先储存所有询问,然后深搜便利所有点,后序遍历找到每个询问中的点,对于每个询都是在两个点都找到的那一刻得到最近公共祖先,后序遍历中不断把点加入并查集中,已加入的最上面的点就是当前的根节点。
解题代码:
#include<iostream>
#include<cstdio>
using namespace std;
int a[10005];
int find(int x,int y)
{
int m1=x,m2,flag=0;
while(true)
{
m2=y;
while(true)
{
if(m1==m2)
{
flag=m1;
break;
}
if(a[m2]==m2)
break;
m2=a[m2];
}
if(flag!=0)
break;
if(a[m1]==m1)
break;
m1=a[m1];
}
return flag;
}
int main()
{
int T,n,node1,node2,ans;
scanf("%d",&T);
for(int i=0;i<T;i++)
{
scanf("%d",&n);
for(int j=0;j<n;j++)
a[j+1]=j+1;
for(int j=0;j<n-1;j++)
{
scanf("%d%d",&node1,&node2);
a[node2]=node1;
}
scanf("%d%d",&node1,&node2);
ans=find(node2,node1);
printf("%d\n",ans);
}
return 0;
}
本题的收获:学会了并查集的使用,通过并查集能够根据父子节点间的关系很快的建树。
解本题所查看过的资料:http://blog.youkuaiyun.com/dellaserss/article/details/7724401/ (并查集详解)