tarjan求强连通分量+缩点 模板

时间:2022-05-12 22:12:30
#define N 100100
#define M 200200

int n,m;
int id,index; //id表示缩点后点的id,index表示进行tarjan算法时访问的点先后
int vis[N],low[N]; //vis表示到当前点的时间,low表示当前所能到达的最小时间.
int stk[N],top; //表示栈
int mark[N];
int link[N]; //将点与缩点后的点相连.
int sum[N]; //强连通分量中点的个数


void dfs(int tarjan_s)
{
    vis[tarjan_s]=++index;
    low[tarjan_s]=vis[tarjan_s];
    stk[top++]=tarjan_s;
    mark[tarjan_s]=1;
    for(int p=pre[tarjan_s];p!=-1;p=edge[p].next)
    {
        int v=edge[p].to;
        if(mark[v]==0) dfs(v);
        if(mark[v]==1) low[tarjan_s]=min(low[v],low[tarjan_s]);
    }
    if(low[tarjan_s]==vis[tarjan_s])//代表找到了一个强连通分量 .
    {
        id++; //这个强连通的标号
        int tarjan_cnt=0;
        do
        {
            tarjan_cnt++;
            int T_tmp=stk[top-1];
            mark[T_tmp]=-1;
            link[T_tmp]=id;
        }while(stk[--top]!=tarjan_s);
        sum[id]=tarjan_cnt;
    }
}

void tarjan()
{
    memset(mark,0,sizeof(mark));
    top=0; index=0; id=0;
    for(int i=1;i<=n;i++)
        if(mark[i]==0) dfs(i);
}