OJ 1234 校园网络

     
 
From easthong
校园网络
 
     
     
  描述 Description  
  一些学校连入一个电脑网络。那些学校已订立了协议:每个学校都会给其它的一些学校分发软件(称作“接受学校”)。注意如果 B 在 A 学校的分发列表中,那么 A 不必也在 B 学校的列表中。

你要写一个程序计算,根据协议,为了让网络中所有的学校都用上新软件,必须接受新软件副本的最少学校数目(子任务 A)。更进一步,我们想要确定通过给任意一个学校发送新软件,这个软件就会分发到网络中的所有学校。为了完成这个任务,我们可能必须扩展接收学校列表,使其加入新成员。计算最少需要增加几个扩展,使得不论我们给哪个学校发送新软件,它都会到达其余所有的学校(子任务 B)。一个扩展就是在一个学校的接收学校列表中引入一个新成员。
     
     
  输入格式 Input Format  
  第一行包括一个整数 N:网络中的学校数目(2 <= N <= 100)。学校用前 N 个正整数标识。接下来 N 行中每行都表示一个接收学校列表(分发列表)。第 i+1 行包括学校 i 的接收学校的标识符。每个列表用 0 结束。空列表只用一个 0 表示。
     
     
  输出格式 Output Format  
  第一行应该包括一个正整数:子任务 A 的解。第二行应该包括子任务 B 的解。
     
     
  样例输入 Sample Input  
 
     
     
  样例输出 Sample Output  
 
     
     
  时间限制 Time Limitation  
  1s
     
     
  注释 Hint  
   
     
     
  来源 Source  
  usaco 5.3.3

这道题有两问

第一问很简单,先tarjin缩一下点,然后找出所有入度为0的点,那么这些点是必须要副本的,其他的点一定可以有这些点到达,所以答案就是所有入度为0的点

第二问,有一个小结论,就是一个有向图我们只需要最多连max(入度为0的点的个数,初度为0的点的个数)条边,那么个图就可以成为强连通的,即从任意一个点可以到达另外所有点,但当只有一个强连通分量的时候要输出0而不是1

#include <bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
    int x=0;int f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int MAXN=1e4+10;
namespace zhangenming{
    struct node{
          int x,y,next;
    }e[MAXN];
    int linkk[MAXN],len=0,n;
    inline void insert(int xx,int yy){
         e[++len].y=yy;e[len].x=xx;e[len].next=linkk[xx];linkk[xx]=len;
    }
   void init(){
       n=read();
       for(int i=1;i<=n;i++){
        int xx=read(); 
           while(xx){
               insert(i,xx);
            xx=read();
           }    
       }
    }
    int vis[MAXN],stark[MAXN],ine[MAXN],cntt[MAXN]={},tot=0,top=0,cnt[MAXN]={},dfn[MAXN]={},low[MAXN],dfs_clock=0;
    inline void tarjin(int st){
        //cout<<st<<endl;
        dfn[st]=low[st]=++dfs_clock;vis[st]=1;
        stark[++top]=st;
        for(int i=linkk[st];i;i=e[i].next){
            if(!dfn[e[i].y]){
                //cout<<e[i].y<<endl;
                tarjin(e[i].y);
                low[st]=min(low[st],low[e[i].y]);
            }
            else if(vis[e[i].y]) low[st]=min(low[st],dfn[e[i].y]);
        }
        if(low[st]==dfn[st]){
            tot++;
            int k;
            do{
                k=stark[top--];
                ine[k]=tot;
                vis[k]=0;
            }while(k!=st);
        }
    }
    void solve(){
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++){
            if(!ine[i]) tarjin(i);
        }
        for(int i=1;i<=len;i++){
            int xx=e[i].x;int yy=e[i].y;
            if(ine[xx]==ine[yy]) continue;
            cnt[ine[yy]]++;
            cntt[ine[xx]]++;
        }
        int sum1=0;int sum2=0;
        for(int i=1;i<=tot;i++){
            if(!cnt[i]) sum1++;
            if(!cntt[i]) sum2++;
        }
        cout<<sum1<<endl;
        if(tot!=1) cout<<max(sum1,sum2)<<endl;
        else cout<<0<<endl;
    }
}
int main(){
    using namespace zhangenming;
    init();
    solve();
    return 0;
}

  

 

posted @ 2017-11-22 22:00  zhangenming  阅读(233)  评论(0编辑  收藏  举报