tarjan算法

补一年前的坑。

有向图强连通分量

inline void tarjan(int x){
    dfn[x]=low[x]=++dt,sta[++tp]=x,ins[x]=1;
    forg(i,x)
        if(!dfn[to[i]])tarjan(to[i]),low[x]=min(low[x],low[to[i]]);
        else if(ins[to[i]])low[x]=min(low[x],dfn[to[i]]);
    if(dfn[x]==low[x]){
        ++bn;int y;
        do y=sta[tp--],ins[y]=0,bel[y]=bn;
        while(x!=y);
    }
}

low数组啥意思我也说不清,大概理解成一个辅助数组吧。。这个算法的妙处就在于,一个强联通分量的所有点,都会在标号最小的那个点那里被统计到。

无向图边双

inline void tarjan(int x,int e){
    dfn[x]=low[x]=++dt;
    forg(i,x)if(!dfn[to[i]]){
        tarjan(to[i],i),low[x]=min(low[x],low[to[i]]);
        if(low[to[i]]>dfn[x])br[i]=br[i^1]=1;
    }else if(i!=(e^1))low[x]=min(low[x],low[to[i]]);
}

无向图点双

void tar(int x,int e){
    dfn[x]=low[x]=++dn,tk[++tn]=x;
    forg(i,x)if(i!=e){
        int y=to[i];if(!dfn[y]){
            tar(y,i^1),low[x]=min(low[x],low[y]);
            if(low[y]==dfn[x]){
                int z;do z=tk[tn--];while(z!=y);
            }else if(low[y]>dfn[x])--tn;
        }else low[x]=min(low[x],dfn[y]);
    }
}

比有向图简单多了。

posted @ 2021-04-03 17:56  yugyppah656  阅读(107)  评论(0编辑  收藏  举报