POJ 2553 The Bottom of a Graph (强连通分量)

题意:求一个有向图中所有满足以下性质的结点:从自身出发可达的点均能回到自身。

分析:求的就是缩点后出度为0的强连通分量内的点。

这题以前写过,当时用邻接表来存储的。今天又试了下矩阵存储,速度慢了一半……

用矩阵存储时,要用char或bool,否则会超内存。

View Code
#include <stdio.h>

#include <string.h>

#define N 5001

int n,m;

char g[N][N],vis[N];

int dfn[N],id[N],cnt;

int dout[N];

void dfs(int u)

{

    vis[u]=1;

    for(int v=1;v<=n;v++)

    {

        if(g[u][v] && !vis[v]) dfs(v);

    }

    dfn[cnt++]=u;

}

void rdfs(int u)

{

    vis[u]=1;

    id[u]=cnt;

    for(int v=1;v<=n;v++)

    {

        if(g[v][u] && !vis[v]) rdfs(v);

    }

}

void solve()

{

    int i,j,t;

    cnt=0;

    memset(vis+1,0,sizeof(char)*n);

    for(i=1;i<=n;i++)

    {

        if(!vis[i]) dfs(i);

    }

    cnt=0;

    memset(vis+1,0,sizeof(char)*n);

    for(t=n-1;t>=0;t--)

    {

        i=dfn[t];

        if(!vis[i]) rdfs(i),cnt++;

    }

    memset(dout,0,sizeof(int)*(n+1));

    for(i=1;i<=n;i++)

    {

        for(j=1;j<=n;j++)

        {

            if(g[i][j] && id[i]!=id[j]) dout[id[i]]++;

        }

    }

    for(i=1;i<=n;i++)   if(!dout[id[i]])    {printf("%d",i);break;}

    for(i++;i<=n;i++)   if(!dout[id[i]])    printf(" %d",i);

    puts("");

}

int main()

{

    int a,b;

    while(scanf("%d",&n),n)

    {

        for(int i=1;i<=n;i++)   memset(g[i],0,sizeof(char)*(n+1));

        scanf("%d",&m);

        while(m--)

        {

            scanf("%d%d",&a,&b);

            g[a][b]=1;

        }

        solve();

    }

    return 0;

}

 

你可能感兴趣的:(Graph)