COJ1128(Download Station)

题目链接

题目大意是给定一个有向图,求最少需添加多少条有向边使得原图强连通。可以先求强连通分量,统计缩点后的图中入度为0的点和出度为0的点,答案就是两者中的较大者,需要注意的是当原图是强连通时,直接输出0。因为没有初始化WA了一次。

#include <stdio.h>

#include <string.h>

#define CLR(a) (memset(a,0,sizeof(a)))

#define N 100

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

int n;

int ord[N],id[N],cnt,din[N],dout[N];

void dfs(int u)

{

    int v;

    vis[u]=1;

    for(v=0;v<n;v++)

    {

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

    }

    ord[cnt++]=u;

}

void rdfs(int u)

{

    int v;

    vis[u]=1,id[u]=cnt;

    for(v=0;v<n;v++)

    {

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

    }

}

void kosaraju()

{

    int i,j,t,a,b;

    CLR(vis);

    for(i=0,cnt=0;i<n;i++)

    {

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

    }

    CLR(vis);

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

    {

        i=ord[t];

        if(!vis[i])

        {

            rdfs(i),cnt++;

        }

    }

    CLR(din),CLR(dout);

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

    {

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

        {

            if((id[i]^id[j]) && (g[i][j] || g[j][i]))

            {

                dout[id[i]]+=g[i][j],din[id[j]]+=g[i][j];

                dout[id[j]]+=g[j][i],din[id[i]]+=g[j][i];

            }

        }

    }

    for(i=0,a=0,b=0;i<cnt;i++)  a+=dout[i]==0?1:0,b+=din[i]==0?1:0;

    if(cnt==1)    printf("0\n");

    else    printf("%d\n",a>b?a:b);

}

int main()

{

    int i,j;

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

    {

        CLR(g);

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

        {

            while(scanf("%d",&j)&&j)   g[i][j-1]=1;

        }

        kosaraju();

    }

    return 0;

}

 

你可能感兴趣的:(download)