zoukankan      html  css  js  c++  java
  • POJ 1236 Network of Schools

    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 16873   Accepted: 6672

    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 Output

    1
    2
    

    Source

    IOI 1996
    题目大意:

    100个学校,有单向网络连接,从而分享软件。给出n个点,接下来n行,第i行的数表示i与这些点相连,以一个0来结束这一行。

    输出要求:第一行输出最少有几个学校得到软件,其余所有学校才可以都得到软件;第二行输出再增加几条单向边,可以使任意一个学校得到软件,其余学校便都可以得到软件。

    思路:Tarjan跑一遍,进行缩点,最后有几个入度为零的点输出就是第一行的答案,第二行需要特判,若是本来就可以缩成一个点,则输出0,否则出度为0的点数和入度为0 的点数取大。。。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<stack>
     5 #define maxn 1005
     6 #define maxm 10005
     7 using namespace std;
     8 int n,m;
     9 struct edge{
    10     int u,v,next;
    11 }e[maxm],ee[maxm];
    12 int head[maxn],js,headd[maxn],jss,bianshu;
    13 bool exist[maxn];
    14 int visx,cur;// cur--缩出的点的数量 
    15 int dfn[maxn],low[maxn],belong[maxn],chudu[maxn],rudu[maxn];
    16 stack<int>st;
    17 void add_edge(int u,int v){
    18     e[++js].u=u;e[js].v=v;
    19     e[js].next=head[u];head[u]=js;
    20 }
    21 void add_edgee(int u,int v){
    22     ee[++jss].u=u;ee[jss].v=v;
    23     ee[jss].next=head[u];head[u]=jss;
    24 }
    25 void tarjan(int u){
    26     dfn[u]=low[u]=++visx;
    27     st.push(u);exist[u]=true;
    28     for(int i=head[u];i;i=e[i].next){
    29         int v=e[i].v;
    30         if(dfn[v]==0) {
    31             tarjan(v);
    32             low[u]=min(low[v],low[u]);
    33         }
    34         else if(exist[v]&&low[u]>dfn[v]) low[u]=dfn[v];
    35     }
    36     int j;
    37     if(low[u]==dfn[u]){
    38         ++cur;
    39         do{
    40             j=st.top();st.pop();
    41             exist[j]=false;belong[j]=cur;
    42         }while(j!=u);
    43     }
    44 }
    45 int main()
    46 {
    47     scanf("%d",&n);
    48     for(int i=1;i<=n;i++){
    49         while(scanf("%d",&m)==1&&m!=0){
    50             add_edge(i,m);bianshu++;
    51         }
    52     }
    53     for(int i=1;i<=n;i++)
    54       if(dfn[i]==0)
    55         tarjan(i);      
    56     for(int i=1;i<=js;i++){
    57         int u=e[i].u,v=e[i].v;
    58         if(belong[u]!=belong[v]){
    59             add_edgee(belong[u],belong[v]);
    60             rudu[belong[v]]++;chudu[belong[u]]++;
    61         }
    62     }
    63     int chu=0,ru=0;
    64     for(int i=1;i<=cur;i++){
    65         if(chudu[i]==0) chu++;
    66         if(rudu[i]==0) ru++;
    67     }
    68     printf("%d
    ",ru);
    69     if(cur==1) printf("%d
    ",0);
    70     else printf("%d
    ",max(ru,chu));
    71     
    72     return 0;
    73 }
  • 相关阅读:
    iOS学习,需要懂的一些基础
    学习RAC小记-适合给新手看的RAC用法总结(转)
    UITableView进阶,cell刷新,界面返回 保持所选cell
    冒泡排序
    ArrayList 实现随机点名
    ArrayList的使用
    java中一维数组的定义和遍历
    java 中二维数组的定义和遍历
    Java 引用数据类型
    java 中自定义类的概述
  • 原文地址:https://www.cnblogs.com/suishiguang/p/6239237.html
Copyright © 2011-2022 走看看