POJ(2186)强连通分量分解

#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int MAX_N=10005;
vector<int> G[MAX_N]; 
vector<int> rG[MAX_N];//存储边反向之后的图 
vector<int> PostOrder;//存储图的后序遍历 
int V,E;
bool used[MAX_N];
int comp[MAX_N];//存储每个结点所属的连通分量 
void addEdge(int u,int v)
{
    G[u].push_back(v);
    rG[v].push_back(u);
}
void dfs(int u)
{
    used[u]=true;
    for(int i=0;i<G[u].size();i++)
    {
        int v=G[u][i];
        if(!used[v])
            dfs(v);
    }
    PostOrder.push_back(u);
}

void rdfs(int u,int k)
{
    used[u]=true;
    comp[u]=k;
    for(int i=0;i<rG[u].size();i++)
    {
        int v=rG[u][i];
        if(!used[v])
            rdfs(v,k);
    }
}

int scc()
{
    memset(used,false,sizeof(used));
    for(int i=1;i<=V;i++)
    {
        if(!used[i])
            dfs(i);
    }
    memset(used,false,sizeof(used));
    int k=0;
    for(int i=PostOrder.size()-1;i>=0;i--)
    {
        int v=PostOrder[i];
        if(!used[v])
            rdfs(v,k++);
    }
    return k;
}
int main()
{
    scanf("%d %d",&V,&E);
    for(int i=0;i<E;i++)
    {
        int u,v;
        scanf("%d %d",&u,&v);
        addEdge(u,v);
    }
    int n=scc();
    int u=0,num=0;
    for(int i=1;i<=V;i++)
    {
        if(comp[i]==n-1)//可能的答案必为最后一个强连通分量
        {
            u=i;
            num++;
        }
    }
    memset(used,false,sizeof(used));
    rdfs(u,0);//若最后一个连通分量的中的一点,能按反向边将所有结点遍历则该联通分量为答案
    for(int i=1;i<=V;i++)
    {
        if(!used[i])
        {
            num=0;
            break;
        }
    }
    printf("%d
",num);
    return 0;
}
原文地址:https://www.cnblogs.com/program-ccc/p/4828558.html