您的位置:首页 > 编程语言 > C语言/C++

C++——【USACO 5.3.3】——Network of Schools

2017-10-25 15:35 816 查看
Network of Schools

IOI '96 Day 1 Problem 3


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.

PROGRAM NAME: schlnet

INPUT FORMAT

The first line of the input file 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.

SAMPLE INPUT (file schlnet.in)

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

OUTPUT FORMAT

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

SAMPLE OUTPUT (file schlnet.out)

1
2


学校网络

许多学校的计算机网络相连。这些学校之间已经达成了协议:每所学校都有一份分发软件的学校名单(“接收学校”)。请注意,如果B在A学校的分配列表中,A并不一定出现在B学校的列表中。

你要编写一个程序,计算选择最小数量的学校来接受一份新的协议使信息可以通过网络传达到所有学校(子任务1)。作为一个进一步的任务,我们希望确保通过网络发送的信息可以到达任意学校。为了实现这一目标,我们可能需要扩大新成员的接收名单。计算最小的扩展数,这样无论我们将新软件发送到哪个学校,它都能到达所有其他学校(子任务2)。一个扩展意味着将一个新成员引入一个学校的接收器列表中。

项目名称:schlnet

输入格式

输入文件的第一行包含一个整数N:网络中的学校数(2 <=N<= 100)。下一个N行描述了一个接收者列表。第i + 1行包含学校i的接收对象的编号,每个列表以0结尾。空列表中包含一个单独的0。

示例输入(文件schlnet.in)

5

2 3 4 0

4 5 0

0

0

1 0

输出格式

你的程序应该写两行到输出文件。第一行应该包含一个正整数:子任务1的解。第二行应该包含子任务2的解。

样例输出(文件schlnet.out)



2

——为了省空间,我循环使用了一些变量。。

/*
ID : mcdonne1
LANG : C++
TASK : schlnet
*/

#pragma GCC optimize("O3")

#include <fstream>
#include <cstring>
#include <algorithm>

using namespace std;

int n, x, cnt, tot;
int to[5000], next[5000], belong[101], first[101], in[101], out[101], st[101];
pair <int, int> p[5000];
bool vis[101];

inline void add (int x, int y) {
to[++cnt] = y;
next[cnt] = first[x];
first[x] = cnt;
}

void dfs (int x) {
vis[x] = true;
for (int i = first[x]; i; i = next[i])
if (!vis[to[i]])
dfs (to[i]);
st[++cnt] = x;
}

void redfs (int x) {
vis[x] = true;
belong[x] = tot;
for (int i = first[x]; i; i = next[i])
if (!vis[to[i]])
redfs (to[i]);
}

int main () {
FILE *fin = fopen("schlnet.in", "r");
FILE *fout = fopen("schlnet.out", "w");
fscanf (fin, "%d", &n);
for (int i = 1; i <= n; i++)
while (fscanf (fin, "%d", &x))
if (x) add (i, x), p[cnt] = make_pair(i, x);
else break;
cnt = 0;
for (int i = 1; i <= n; i++) if (!vis[i]) dfs (i);
cnt = 0;
memset (to, 0, sizeof(to));
memset (vis, 0, sizeof(vis));
memset (next, 0, sizeof(next));
memset (first, 0, sizeof(first));
fseek (fin, 0, SEEK_SET);
fscanf (fin, "%d", &n);
for (int i = 1; i <= n; i++) while (fscanf (fin, "%d", &x)) if (x) add (x, i); else break;
for (int i = n; i >= 1; i--) if (!vis[st[i]]) ++tot, redfs (st[i]);
for (int i = 1; i <= cnt; i++)
if (belong[p[i].first] ^ belong[p[i].second])
++out[belong[p[i].first]], ++in[belong[p[i].second]];
x = cnt = 0;
for (int i = 1; i <= tot; i++) {
if (!in[i]) ++cnt;
if (!out[i]) ++x;
}
if (tot == 1) fprintf (fout, "1\n0\n");
else fprintf (fout, "%d\n%d\n", cnt, max (cnt, x));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: