Network of Schools
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 8935 Accepted: 3523
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
水题。题目有两问,第一问求的是找到最少的点使得信息能覆盖整个图,第二问是加最少的边使该图成为强连通图。直接用tarjan求出各强连通分量,进行缩点,显然选择所有入度为0的点就能覆盖整个图了。几乎入度为0和出度为0的点的个数,二者中较大者就是需要添加的边数。随便画个图就一目了然了。注意只有一个强连通分量时,说明图本来就是强连通的,这时应该输出1和0。这里如果不特判一下,将输出1和1得到WA。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
#define SIZE 128
using namespace std;
struct node
{
int to,next;
}edge[SIZE*SIZE];
int head[SIZE],idx;
int dfsn[SIZE],low[SIZE],time;
bool vis[SIZE];
int belong[SIZE],num,in[SIZE],out[SIZE];
stack <int> sta;
int N;
void addnode(int from,int to)
{
edge[idx].to = to;
edge[idx].next = head[from];
head[from] = idx++;
}
void tarjan(int rt)
{
dfsn[rt] = low[rt] = ++time;
sta.push(rt);
vis[rt] = true;
for(int i=head[rt]; i!=-1; i=edge[i].next)
{
int to = edge[i].to;
if(!dfsn[to])
{
tarjan(to);
if(low[to] < low[rt])
low[rt] = low[to];
}
else if(vis[to] && dfsn[to] < low[rt])
low[rt] = dfsn[to];
}
int t = 0;
if(dfsn[rt] == low[rt])
{
num ++;
while(t != rt)
{
t = sta.top();
sta.pop();
vis[t] = false;
belong[t] = num;
}
}
}
void solve()
{
memset(dfsn,0,sizeof(dfsn));
memset(vis,0,sizeof(vis));
memset(belong,0,sizeof(belong));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
time = num = 0;
for(int i=1; i<=N; i++)
if(!dfsn[i])
tarjan(i);
if(num == 1)
{
puts("1");
puts("0");
return;
}
for(int i=1; i<=N; i++)
{
for(int j=head[i]; j!=-1; j=edge[j].next)
{
int to = edge[j].to;
if(belong[i] != belong[to])
{
out[belong[i]] ++;
in[belong[to]] ++;
}
}
}
int IN = 0, OUT = 0;
for(int i=1; i<=num; i++)
{
if(!in[i]) IN++;
if(!out[i])OUT++;
}
printf("%d\n",IN);
printf("%d\n",max(IN,OUT));
}
int main()
{
while(~scanf("%d",&N))
{
int tem;
idx = 0;
memset(head,-1,sizeof(head));
for(int i=1; i<=N; i++)
{
while(scanf("%d",&tem) && tem)
addnode(i,tem);
}
solve();
}
return 0;
}
本文探讨了在特定网络环境中,通过最小数量的节点传播软件的策略,包括找到覆盖整个网络所需的最少节点(子任务A),以及通过最少的连接扩展来确保任意节点都能传播到整个网络(子任务B)。采用Tarjan算法求解强连通分量,并利用其特性解决上述问题。
788

被折叠的 条评论
为什么被折叠?



