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;
}

 

posted @ 2012-07-26 21:10  BeatLJ  阅读(191)  评论(0编辑  收藏  举报