您的位置:首页 > 其它

POJ 1236 Network of Schools (强连通分量+缩点)

2013-05-30 09:39 323 查看
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;
}


 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: