COGS 908 校园网

/*
Tarjan缩点之后 
强联通分量建图 统计每个强联通分量的出入度
第一问就是入度为0的 强联通分量的个数
第二问 为了高效的使每个强联通分量都有出入度
要把出度为零的强联通分量连到入度为零的点上 这样得到的边数是最少的
ans2并不是桥的数目 这样不是最少..... 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 110
#define maxm 10010
using namespace std;
int n,num,g[maxn][maxn],head[maxn],sum,tot,belong[maxn];
int dfn[maxn],low[maxn],stack[maxm],top,f[maxn],ans1,ans2;
int chu[maxn],ru[maxn];
struct node
{
    int u,v,pre;
}e[maxm];
struct Node
{
    int c[maxn];
    int size;
}ans[maxn];
int init()
{
    int x=0;char s;bool f=0;s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    if(f)return -x;return x;
}
void Add(int from,int to)
{
    num++;
    e[num].u=from;
    e[num].v=to;
    e[num].pre=head[from];
    head[from]=num;
}
void Tarjan(int s)
{
    dfn[s]=low[s]=++tot;
    stack[++top]=s;
    f[s]=1;
    for(int i=head[s];i;i=e[i].pre)
      {
          if(!dfn[e[i].v])
            {
                Tarjan(e[i].v);
                low[s]=min(low[s],low[e[i].v]);
          }
        else if(f[e[i].v])
          low[s]=min(low[s],dfn[e[i].v]);
      }
    if(dfn[s]==low[s])
      {
          sum++;
          while(s!=stack[top])
            {
                ans[sum].size++;
                belong[stack[top]]=sum;
                ans[sum].c[ans[sum].size]=stack[top];
                f[stack[top]]=0;
                top--;
          }
        ans[sum].size++;
        belong[stack[top]]=sum;
          ans[sum].c[ans[sum].size]=stack[top];
          f[stack[top]]=0;
          top--;
      }
}
int main()
{
    //freopen("schlnet.in","r",stdin);
    //freopen("schlnet.out","w",stdout);
    n=init();
    int x;
    for(int i=1;i<=n;i++)
      while(1)
        {
            x=init();
            if(x==0)break;
            Add(i,x);
        }
    for(int i=1;i<=n;i++)
      if(!dfn[i])
        Tarjan(i);
    for(int i=1;i<=n;i++)
      {
          for(int j=head[i];j;j=e[j].pre)
            {
                if(belong[i]!=belong[e[j].v])
                  {
                if(g[belong[i]][belong[e[j].v]]==0)
                  {
                      chu[belong[i]]++;
                          ru[belong[e[j].v]]++;
                  }
                g[belong[i]][belong[e[j].v]]=1;
              }
          }
      }
    for(int i=1;i<=sum;i++)
      {
          if(ru[i]==0)ans1++;
          if(chu[i]==0)ans2++;
      }
    if(sum==1)
      {
          printf("1
0
");
          return 0;
      }
    printf("%d
%d
",ans1,max(ans1,ans2));
    return 0;
}
原文地址:https://www.cnblogs.com/yanlifneg/p/5494567.html