Tarjan-LCA算法小记

Posted dilthey

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tarjan-LCA算法小记相关的知识,希望对你有一定的参考价值。

Tarjan-LCA算法是一种离线算法。

 

算法描述:

DFS遍历每个节点,对于遍历到的当前节点u:

①建立以u为代表元素的集合。

②遍历与u相连的节点v,如果没有被访问过,对于v使用Tarjan-LCA算法,结束后,将v的集合并入u的集合。

③对于与u有关的询问Query(u,v),如果v被访问过,则LCA(u,v)为v所在集合的代表元素。

 

代码模板:

const int maxn=10005; //节点数
const int maxm=10005; //边数
const int maxq=10005; //查询数

int par[maxn];
int find(int x){return (par[x]==x)?x:(par[x]=find(par[x]));}

struct Edge{
    int u,v;
    Edge(int u=0,int v=0){this->u=u,this->v=v;}
};
vector<Edge> E;
vector<int> Ge[maxn];
void addedge(int u,int v)
{
    E.push_back(Edge(u,v));
    Ge[u].push_back(E.size()-1);
}

struct Query{
    int u,v;
    int lca;
    Query(int u=0,int v=0,int lca=0){this->u=u,this->v=v,this->lca=lca;}
};
vector<Query> Q;
vector<int> Gq[maxn];
void addquery(int u,int v,int lca)
{
    Q.push_back(Query(u,v,lca));
    Gq[u].push_back(Q.size()-1);
}

bool vis[maxn];
void LCA(int u)
{
    par[u]=u; //建立以u为代表元素的集合
    vis[u]=1;
    for(int i=0;i<Ge[u].size();i++)
    {
        Edge &e=E[Ge[u][i]]; int v=e.v;
        if(!vis[v])
        {
            LCA(v);
            par[v]=u; //将v的集合并入u的集合
        }
    }
    for(int i=0;i<Gq[u].size();i++)
    {
        Query &q=Q[Gq[u][i]]; int v=q.v;
        if(vis[v])
        {
            q.lca=find(v);
            Q[Gq[u][i]^1].lca=q.lca;
        }
    }
}

 

时间复杂度:

DFS遍历图O(n),枚举查询O(q),总的就是O(n+q)。

以上是关于Tarjan-LCA算法小记的主要内容,如果未能解决你的问题,请参考以下文章

2017/09/06:算法练习小记

2018.07.29(搜索)学习DFS算法小记

算法小记

算法小记

Cipolla算法学习小记

算法小记