tarjan算法

Posted 无尽的蓝黄

tags:

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

定义

dfn[x]:DFN过程中到x点的时间
low[x]:最小的x能达到的点的dfn
当x进栈时dfn[x]=low[x]
part[x]:x所在的强连通分量

代码解释

//强连通分量
int tarjan(int x)
{
    d[++tot]=x;//进栈
    dfn[x]=low[x]=++dd;//初始化dfn[]以及low[]
    for(int i=last[x];i;i=next[i])
    {
        int j=to[i];
        if(!dfn[j])//当没走过j是,遍历j
        {
            tarjan(j);
            low[x]=min(low[x],low[j]);//因为x可以走到j,所以更新low[]
        }
        else
        if(!part[j])//只有当j还在栈中是才可以更新low。因为当j不在栈中时,j并不能遍历到x
            low[x]=min(low[x],low[j]);
    }
    if(dfn[x]==low[x])//表示x无法回溯到更小的dfn
    {
        num++;//num表示强连通分量个数
        while(dfn[d[tot]]>=dfn[x])//退栈,在栈中比x后进栈的节点都与x属于同一个强连通分量
        {
            part[d[tot--]]=num;
        }
    }
}
//人工栈代码
long long tarjan(long long x1)
{
    z[top=1]=x1;
    while(top)
    {
        long long x=z[top];
        if(!dfn[x])
        {
            dfn[x]=low[x]=++tot;
            d[++dd]=x;
        }
        long long i;
        for(i=last[x];i;i=next[i])
        {
            if(!dfn[to[i]])
            {
                break;
            }
            else
            if(!belong[to[i]])
                low[x]=min(low[to[i]],low[x]);
        }
        if(!i && top>1) 
            low[z[top-1]]=min(low[z[top-1]],low[x]);
        if(!i)
        {
            if(dfn[x]==low[x])
            {
                be++;
                while(dd && low[d[dd]]>=dfn[x])
                {
                    belong[d[dd]]=be;
                    sum[be]+=a[d[dd]];
                    dd--;
                }
            }
            top--;
        }
        else
            z[++top]=to[i];
    }
}
//双连通分量
int tarjan(int x,int fa)
{
    low[x]=dfn[x]=++tot;
    d[++dd]=x;
    for(int i=last[x];i;i=next[i])
    {
        int j=to[i];
        if(i!=fa)//类似于强连通分量,只有保证不走来的边就可以了
        {
            if(!dfn[j])
            {
                tarjan(j,i^1);
                low[x]=min(low[x],low[j]);
            }
            else
                low[x]=min(low[x],dfn[j]);
        }
    }
    if(low[x]==dfn[x])
    {
        num++;
        while(low[d[dd]]>=dfn[x] && dd)
        {
            part[d[dd--]]=num;
            sum[num]++;
        }
    }
}

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

tarjan割点算法代码实现

HDU 1269 迷宫城堡 tarjan算法求强连通分量

Tarjan-LCA算法小记

关于tarjan

模板强连通分量和tarjan算法

有向图的强连通算法 -- tarjan算法