uvaUVA - 11354 ???
一个比较好的博客给出了大体思路 点击打开链接
;
lca问题可以同RMQ问题之间相互转化;
总体而言分为五种解法:
解法一:暴力对待
通过二叉查找树进行操作:
;
解法二:Tarjan算法
poj1330
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
using namespace std;
const int maxn=10000+5;
int ans[maxn];
int ran[maxn];
int pro[maxn];
int vis[maxn];
int inter[maxn];
vector<int> que[maxn];
vector<int> tree[maxn];
void init(int n)
{
for(int i=0;i<=n;i++)
{
ran[i]=1;
pro[i]=i;
que[i].clear();
tree[i].clear();
ans[i]=0;
vis[i]=0;
inter[i]=0;
}
}
int find(int x)
{
if(pro[x]==x)
return x;
else
return pro[x]=find(pro[x]);
}
void uion(int x,int y)
{
int xx=find(x);
int yy=find(y);
if(xx==yy)
return;
else if(ran[xx]<ran[yy])
{
pro[xx]=yy;
ran[yy]+=ran[xx];
}
else
{
pro[yy]=xx;
ran[xx]+=ran[yy];
}
}
void lca(int u)
{
ans[u]=u;
for(int i=0;i<tree[u].size();i++)
{
lca(tree[u][i]);
uion(u,tree[u][i]);
ans[find(u)]=u;
}
vis[u]=1;
for(int i=0;i<que[u].size();i++)
{
if(vis[que[u][i]])
cout<<ans[find(que[u][i])]<<endl;
}
}
int main()
{
int T,n;
cin>>T;
while(T--)
{
cin>>n;
init(n);
for(int i=0;i<n-1;i++)
{
int x,y;
cin>>x>>y;
tree[x].push_back(y);
//ran[x]++;
inter[y]++;
}
int s,t;
cin>>s>>t;
que[s].push_back(t);
que[t].push_back(s);
for(int i=1;i<=n;i++)
{
if(inter[i]==0)
{
lca(i);
break;
}
}
}
return 0;
}
解法三:转换为RMQ问题
解法四:线段树
其余解法
除此之外,还有倍增法、重链剖分算法和后序遍历也可以解决该问题。其中,倍增思路相当于层序遍历,逐层或几层跳跃查,查询时间复杂度为O(log n),空间复杂度为nlogn,对于每个节点先存储向上1层2层4层的节点,每个点有depth信息。