USACO Network of Schools(学校网络) ---强连通分量

描述

一些学校的校园网连接在一个计算机网络上。学校之间存在软件支援协议。每个学校都有它应支援的学校名单(学校a支援学校b,并不表示学校b一定支援学校a)。当某校获得一个新软件时,无论是直接得到的还是从网络得到的,该校都应立即将这个软件通过网络传送给它应支援的学校。因此,若需要让所有连接在网络上的学校都能使用一个新软件,只需要将其提供给其中一些学校即可。

子任务a:根据学校间软件支援协议(各个学校的支援名单),计算最少需要将一个软件直接提供给多少个学校,才能使该软件通过网络传送到所有学校。

子任务b:如果允许在原有支援协议上添加新的支援关系,则总可以形成一个新的协议,使得此时只需要将一个新软件提供给任何一个学校,其他所有学校就都可以通过网络获得该软件。请计算出最少需要添加几条新的支援关系。

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.

格式

输入格式

第一行是一个整数 n(2≤n≤100),表示与网络连接的学校总数。接下来 n行描述了每个学校要支援的学校。第i+1行表示第i 号学校要支援的所有学校的编号,编号之间用空格隔开,每行以数字0 结束。如果某个学校不支援任何学校,则相应的行会有一个0。

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.

输出格式

包含两行,第一行是一个正整数,表示子任务a的解。第二行也是一个正整数,表示子任务b的解。

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.

样例1

样例输入1

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

样例输出1

1
2

提示

图结构

来源

安徽省芜湖市二十七中练习题

IOI 1996 Network of Schools(NET)

Description:Official(English)/Unknown(Chinese Simplified)
Data:Official
Program:JackDavid127

 

 1 /*
 2     tarjan求强连通分量
 3     第一问 缩点建新图 求入度为0点的个数
 4     第二问 只需将整个图变成一个连通图
 5            那么求入度出度中最大值  
 6 */
 7 #include<cstdio>
 8 #include<iostream>
 9 #define MAXN 1000
10 
11 using namespace std;
12 
13 int n,in[MAXN],ans,ans1,cu[MAXN];
14 
15 int dfn[MAXN],low[MAXN],stack[MAXN],belong[MAXN],inr,top,cnt;
16 bool vis[MAXN];
17 
18 struct node {
19     int to;
20     int next;
21 };
22 node e[MAXN*10];
23 int head[MAXN],tot;
24 
25 inline void read(int&x) {
26     x=0;int f=1;char c=getchar();
27     while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
28     while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-48;c=getchar();}
29     x=x*f;
30 }
31 
32 inline void add(int x,int y) {
33     e[++tot].to=y;
34     e[tot].next=head[x];
35     head[x]=tot;
36 }
37 
38 inline void tarjan(int u) {
39     dfn[u]=low[u]=++inr;
40     vis[u]=true;
41     stack[++top]=u;
42     for(int i=head[u];i;i=e[i].next) {
43         int v=e[i].to;
44         if(!dfn[v]) {
45             tarjan(v);
46             low[u]=min(low[u],low[v]);
47         }
48         else if(vis[v]) low[u]=min(low[u],dfn[v]);
49     }
50     if(dfn[u]==low[u]) {
51         ++cnt;
52         int t;
53         do {
54             t=stack[top--];
55             vis[t]=false;
56             belong[t]=cnt;
57         }while(u!=t);
58     }
59 }
60 
61 int main() {
62     int x;
63     read(n);
64     for(int i=1;i<=n;i++) {
65         for(read(x);x!=0;read(x)) add(i,x);
66     }
67     for(int i=1;i<=n;i++)
68       if(!dfn[i])
69         tarjan(i);
70     for(int i=1;i<=n;i++)
71       for(int j=head[i];j;j=e[j].next) {
72           int v=e[j].to;
73           if(belong[i]!=belong[v])
74             in[belong[v]]++;
75             cu[belong[i]]++;
76       }
77     for(int i=1;i<=cnt;i++) {
78           if(!in[i]) ans++;
79           if(!cu[i]) ans1++;
80     }
81     if(cnt==1) {
82         printf("%d\n",cnt);
83         printf("0\n");
84     }
85     else printf("%d\n%d\n",ans,max(ans,ans1));
86     return 0;
87 } 
代码

 

posted @ 2017-06-15 21:23  拿叉插猹哈  阅读(307)  评论(0编辑  收藏  举报