LCA 最近公共祖先问题

来源:互联网 发布:青海网络广播电视台 编辑:程序博客网 时间:2024/05/16 18:19

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信息。




原创粉丝点击