poj 2186 tarjan求强连通分量(模板题)

#include<stdio.h>
#include<string.h>
#include<string>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>

using namespace std;
const int N=100010;

int isin[N],dfn[N],low[N],bel[N];
vector<int>g[N];
int bnt,cnt;
stack<int>s;
int n,m;

void dfs(int i)
{
    dfn[i]=low[i]=++cnt;
    isin[i]=1;
    s.push(i);
    int j;
    for(j=0;j<g[i].size();j++)
    {
        int nn=g[i][j];
        if(!dfn[nn]){
            dfs(nn);
            low[i]=min(low[i],low[nn]);
        }
        if(isin[nn]==1&&low[nn]<low[i]){//子节点在堆栈中,而且low值小于
           low[i]=low[nn];
        }
    }
    if(dfn[i]==low[i]){
        bnt++;
        do{
           j=s.top();
           s.pop();
           isin[j]=false;
           bel[j]=bnt;
       }while(j!=i);//这里不要改成while(i!=j)虽然我也不知道为啥...
    }
}

int solve()
{
    memset(low,0,sizeof(low));
    memset(bel,-1,sizeof(bel));
    memset(dfn,0,sizeof(dfn));
    memset(isin,0,sizeof(isin));
    cnt=bnt=0;
    for(int i=0;i<n;i++)
    {
        if(!dfn[i])dfs(i);
    }
    return bnt;
}

int is[N],tongji[N];

int dfs_1()
{
    memset(is,0,sizeof(is));
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<g[i].size();j++)
        {
            int v=g[i][j];
            if(bel[i]!=bel[v]){
                is[bel[i]]=1;
            }
        }
    }
    int cnt=0;
    int no=-1;
    //cout<<bnt<<endl;
    for(int i=1;i<=bnt;i++){
        if(is[i]==0){
            cnt++;
            no=i;
        }
    }
    //cout<<cnt<<" "<<no<<endl;
    if(cnt==1)
       return no;
    else
       return -1;

}

int main(){
    int i,j;
    int a,b;
    scanf("%d%d",&n,&m);
    for(i=0;i<m;i++){
       scanf("%d%d",&a,&b);
       g[a-1].push_back(b-1);
    }
    int ret=0;
    solve();
    memset(tongji,0,sizeof(tongji));
    for(i=0;i<n;i++){
       tongji[bel[i]]++;
    }
    ret=dfs_1();
    if(ret>0)
       printf("%d
",tongji[ret]);
    else
       printf("0
");
    return 0;
}


原文地址:https://www.cnblogs.com/wlxtuacm/p/5712280.html