zoukankan      html  css  js  c++  java
  • POJ 1236 Network of Schools (有向图的强连通分量)

    Network of Schools
    Time Limit: 1000MS   Memory Limit: 10000K

    Description

    A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a list of schools to which it distributes software (the “receiving schools”). Note that if B is in the distribution list of school A, then A does not necessarily appear in the list of school B 
    You are to write a program that computes the minimal number of schools that must receive a copy of the new software in order for the software to reach all schools in the network according to the agreement (Subtask A). As a further task, we want to ensure that by sending the copy of new software to an arbitrary school, this software will reach all schools in the network. To achieve this goal we may have to extend the lists of receivers by new members. Compute the minimal number of extensions that have to be made so that whatever school we send the new software to, it will reach all other schools (Subtask B). One extension means introducing one new member into the list of receivers of one school. 

    Input

    The first line contains an integer N: the number of schools in the network (2 <= N <= 100). The schools are identified by the first N positive integers. Each of the next N lines describes a list of receivers. The line i+1 contains the identifiers of the receivers of school i. Each list ends with a 0. An empty list contains a 0 alone in the line.

    Output

    Your program should write two lines to the standard output. The first line should contain one positive integer: the solution of subtask A. The second line should contain the solution of subtask B.

    Sample Input

    5
    2 4 3 0
    4 5 0
    0
    0
    1 0
    

    Sample Output1

    2


    题目大意:有N个学校,从每个学校都能从一个单向网络到另外一个学校,两个问题
    1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。
    2:至少需要添加几条边,使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。
    用Tarjan将强连通分量求出来缩点,得到一个scc的图
    统计这个图有多少个入度为0的点ans1,出度为0的点ans2
    则第一个问就是ans1,第二个就是max(ans1,ans2)
    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    using namespace std;
    
    const int MAXN = 100+10;
    const int MAXE = 100*100+100;
    
    struct Edge{
        int to,next;
    };
    Edge edge[MAXE];
    int head[MAXN],tot;
    int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];
    int Index,top;
    int scc;
    bool Instack[MAXN];
    
    void init()
    {
        tot=0;
        memset(head,-1,sizeof(head));
    }
    
    void addedge(int u,int v)
    {
        edge[tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    
    void Tarjan(int u)
    {
        int v;
        Low[u]=DFN[u]=++Index;
        Stack[top++]=u;
        Instack[u]=true;
        for(int i=head[u];i!=-1;i=edge[i].next){
            v=edge[i].to;
            if(!DFN[v]){
                Tarjan(v);
                if(Low[u]>Low[v]) Low[u]=Low[v];
            }
            else if(Instack[v]&&Low[u]>DFN[v])
                Low[u]=DFN[v];
        }
        if(DFN[u]==Low[u]){
            scc++;
            do{
                v=Stack[--top];
                Belong[v]=scc;
                Instack[v]=false;
            }
            while(v!=u);
        }
    }
    
    void solve(int n)
    {
        memset(DFN,0,sizeof(DFN));
        memset(Instack,false,sizeof(Instack));
        Index=top=scc=0;
        for(int i=1;i<=n;i++)
            if(!DFN[i])
               Tarjan(i);
    }
    
    int in[MAXN],out[MAXN];
    
    int main()
    {
        int n;
        int v;
        scanf("%d",&n);
        init();
        for(int i=1;i<=n;i++){
            while(scanf("%d",&v)==1&&v)
                addedge(i,v);
        }
        solve(n);
        if(scc==1){
            printf("1
    0
    ");
            return 0;
        }
        for(int i=1;i<=scc;i++)
            in[i]=out[i]=0;
        for(int u=1;u<=n;u++){
            for(int i=head[u];i!=-1;i=edge[i].next){
                v=edge[i].to;
                if(Belong[u]==Belong[v]) continue;
                out[Belong[u]]++;
                in[Belong[v]]++;
            }
        }
        int ans1=0,ans2=0;
        for(int i=1;i<=scc;i++){
            if(in[i]==0) ans1++;
            if(out[i]==0) ans2++;
        }
        printf("%d
    %d
    ",ans1,max(ans1,ans2));
    
        return 0;
    }
     
  • 相关阅读:
    Node.js入门学习笔记
    Memcached服务器安装、配置、使用详解
    基于Dubbo框架构建分布式服务
    Apache Beam:一个开源的统一的分布式数据处理编程库
    Spring Cloud Netflix构建微服务入门实践
    内部排序算法:快速排序
    内部排序算法:冒泡排序
    内部排序算法:基数排序
    Java常见面试题
    svn+ssh方式svn服务器和客户端的配置[转载]
  • 原文地址:https://www.cnblogs.com/wangdongkai/p/5603849.html
Copyright © 2011-2022 走看看