poj1236学校网络——连通块

题目:http://poj.org/problem?id=1236

通过传输文件的特点可以看出要先求强联通分量,缩点;

问题1:即缩点后入度为0的点,从它们开始传文件可以传给所有学校;

问题2:对于所有入度为0、出度为0的点,对应连一条边;多余的随便再连一下就可以,所以答案是max(入度为0点数,出度为0点数);

需要特判一下没有入度为0的点,也就是整个图是一个强联通分量时,输出1和0。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const MAXN=105;
int n,head[MAXN],ct,dfn[MAXN],low[MAXN],rd[MAXN],cd[MAXN],ans,sta[MAXN],tim,top;
int cr,col[MAXN],r0,c0;
bool vis[MAXN];
struct N{
    int hd,to,next;
    N(int h=0,int t=0,int n=0):hd(h),to(t),next(n) {}
}edge[MAXN*MAXN];
void tarjan(int x)
{
//    cout<<x<<endl;
    tim++;
    dfn[x]=tim;low[x]=tim;
    vis[x]=1;sta[++top]=x;
    for(int i=head[x];i;i=edge[i].next)
    {
        int u=edge[i].to;
        if(!dfn[u])
        {
            tarjan(u);
            low[x]=min(low[x],low[u]);
        }
        else if(vis[u])
            low[x]=min(low[x],dfn[u]);
    }
    if(dfn[x]==low[x])
    {
        cr++;
        while(sta[top]!=x)
        {
            int t=sta[top];
            vis[t]=0;col[t]=cr;
            top--;
        }
        vis[x]=0;col[x]=cr;top--;
    }
}
int main()
{
    scanf("%d",&n);
    int x;
    for(int i=1;i<=n;i++)
        while(1)
        {
            scanf("%d",&x);
            if(!x)break;
            edge[++ct]=N(i,x,head[i]);head[i]=ct;
        }
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            tarjan(i);
    for(int i=1;i<=ct;i++)
    {
        int u=edge[i].hd;
        int v=edge[i].to;
        if(col[u]!=col[v])
        {
            rd[col[v]]++;cd[col[u]]++;
        }
    }
    for(int i=1;i<=cr;i++)
    {
        if(!rd[i])r0++;
        if(!cd[i])c0++;
    }
    if(cr==1)printf("1
0");
    else printf("%d
%d",r0,max(r0,c0));
    return 0;
}
原文地址:https://www.cnblogs.com/Zinn/p/8868519.html