洛谷P2746 POJ1236校园网Network of Schools

洛谷P2746 POJ1236校园网Network of Schools

Title

Time Limit: 1000MS
Memory Limit: 10000K

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

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

翻译

学校网络

时限: 1000MS
内存限制: 10000K

描述

许多学校都连接到计算机网络。这些学校之间已经制定了协议:每所学校都维护着向其分发软件的学校列表(“接收学校”)。请注意,如果B在学校A的分发列表中,则A不一定会出现在学校B的列表中
您将编写一个程序,该程序计算必须收到新软件的副本才能使该软件根据协议到达网络中所有学校的最少学校数量(子任务A)。作为进一步的任务,我们要确保通过将新软件的副本发送到任意学校,该软件将到达网络中的所有学校。为了实现这一目标,我们可能必须扩大新成员的接收者列表。计算必须进行的最小扩展数,以便无论我们将新软件发送到哪个学校,它都将遍及所有其他学校(子任务B)。一种扩展意味着将一名新成员介绍到一所学校的接收者列表中。

输入

第一行包含一个整数N:网络中的学校数量(2 <= N <= 100)。学校由前N个正整数标识。接下来的N行中的每行都描述了一个接收方列表。第i + 1行包含学校i的接收者的标识符。每个列表以0结尾。一个空列表在该行中仅包含0。

输出

您的程序应在标准输出中写入两行。第一行应包含一个正整数:子任务A的解。第二行应包含子任务B的解。

样本输入

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

样本输出

1
2

思路

找出强连通分量,缩点。
缩点可以用拓扑、Floyd、Tanjan
第1问
ans=入度为0的点数(缩点后)
第2问
ans=max(入度为0的点数,出度为0的点数)(缩点后)

Code

#include<iostream> 
#include<cstdio>
#include<stack>
using namespace std;
int dfn[210],low[210],col[210],s[210],ins[210],outs[210],e[210][210],tot,len,cnt;
stack<int>stck;
void Tanjan(int x)
{
    
    
	dfn[x]=low[x]=++tot;stck.push(x);
	for(int i=1;i<e[x][0];i++)
		if(!dfn[e[x][i]])Tanjan(e[x][i]),low[x]=min(low[x],low[e[x][i]]);
		else if(!col[e[x][i]])low[x]=min(low[x],dfn[e[x][i]]);
	if(dfn[x]==low[x])
	{
    
    
		for(col[x]=++len,s[len]=1;stck.top()!=x;stck.top(),stck.pop())col[stck.top()]=len,s[len]++;
		stck.pop();
	}
	return;
}
int main() 
{
    
    
	ios::sync_with_stdio(false);
	int n,m,i,j,ansin,ansout;
	for(cin>>n,i=1;i<=n;i++)
		for(cin>>e[i][++e[i][0]];e[i][e[i][0]];cin>>e[i][++e[i][0]]);
	for(i=1;i<=n;i++)if(!dfn[i])Tanjan(i);
	for(i=1;i<=n;i++)
		for(j=1;j<e[i][0];j++)
			if(col[i]!=col[e[i][j]])ins[col[e[i][j]]]=1,outs[col[i]]=1;
	for(ansin=ansout=0,i=1;i<=len;i++)
		ansin+=!ins[i],ansout+=!outs[i];
	if(len==1)cout<<"1\n0\n";
	else cout<<ansin<<endl<<max(ansin,ansout)<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_46975572/article/details/116398780
今日推荐