有向图的强连通分量/Tarjan缩点

代码

#include<bits/stdc++.h>
using namespace std;
const int N=10010,M=50100;
int h[N],e[M],nex[M],idx;  
//存边
int id[N],dfn[N],low[N],timestamp; 
//id表示每个点属于的强连通分量的编号,dfn,low表时间戳 
int sk[N],st[N],top;    
//sk是栈,st记录点当前是否在栈中
int din[N],dout[N],Size[N],scc_cnt;    
//din,dout,Size表示强连通分量的入度,出度和大小,scc_cnt记录强连通分量个数
void add(int u,int v){
    e[idx]=v;
    nex[idx]=h[u];
    h[u]=idx++;
}
void tarjan(int u){
    dfn[u]=low[u]=++timestamp;
    sk[top++]=u;st[u]=1;
    for(int i=h[u];~i;i=nex[i]){
        int v=e[i];
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(st[v]) low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u]){
        scc_cnt++;
        int v;
        do{
            v=sk[--top];
            st[v]=0;
            id[v]=scc_cnt;
            Size[scc_cnt]++;
        }while(v!=u);
    }
}
int main(){
    int n,m;
    memset(h,-1,sizeof h);
    cin>>n>>m;
    for(int i=1;i<=m;++i){
        int u,v;
        cin>>u>>v;
        add(u,v);
    }
    for(int i=1;i<=n;++i){
        if(!dfn[i]) tarjan(i);
    }
}
原文地址:https://www.cnblogs.com/jjl0229/p/12774438.html