强连通分量模版

Kosaraju算法

借助反图获得好的dfs遍历顺序

int bel[maxn],stk[maxn],top,blocks;
bool vis[maxn];
vector<int>G1[maxn],G2[maxn];
inline void dfs1(int u)
{
    if(vis[u]) return;
    vis[u]=1;
    for(int i=0;i<G1[u].size();i++){
        dfs1(G1[u][i]);
    }
    stk[top++]=u;
    return;
}
inline void dfs2(int u)
{
    if(bel[u]) return;
    bel[u]=blocks;
    for(int i=0;i<G2[u].size();i++){
        dfs2(G2[u][i]);
    }
    return;
}
inline void Kosaraju(int n)
{
    for(int i=1;i<=n;i++) dfs1(i);
    for(int i=n-1;i>=0;i--){
        if(bel[stk[i]]) continue;
        ++blocks;
        dfs2(stk[i]);
    }
    return;
}

 

Tarjan算法

借助时间戳+dfs,注意有向图dfs森林可能有横向边

struct E
{
    int to,next;
}edge[maxm];
int head[maxn],tol;
inline void Addedge(int u,int v)
{
    edge[tol].to=v;edge[tol].next=head[u];head[u]=tol++;
    return;
}
int dfn[maxn],low[maxn],stk[maxn],bel[maxn],tot,top,blocks;
inline void Tarjan(int u)
{
    dfn[u]=low[u]=++tot;
    stk[top++]=u;
    int v;
    for(int i=head[u];i!=-1;i=edge[i].next){
        v=edge[i].to;
        if(!dfn[v]){
            Tarjan(v);
            if(low[v]<low[u]) low[u]=low[v];
        }
        else if(!bel[v]&&dfn[v]<low[u]) low[u]=dfn[v];
        //bel[v]==0确保v在当前scc中
    }
    if(low[u]==dfn[u]){
        ++blocks;
        do{
            v=stk[--top];
            bel[v]=blocks;
        }while(v!=u);
    }
    return;
}

 

时间复杂度:O(n+m) 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值