题目链接:
http://poj.org/problem?id=1236
Network of Schools
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 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 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 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 Source |
[Submit] [Go Back] [Status]
[Discuss]
题目意思:
给出每个学校能够传送信息的学校名单。
求Subtask A:至少要给多少个学校发送源信息,才能是所有学校都收到信息。求Subtask B:求至少需要添加几个接受信息学校,使得当信息发送给任意一个学校时,都能传送到其他学校。
解题思路:
先求有向图的强连通分量。然后缩点。统计各点出度和入度。
Subtask A 就是求入度为0的点的个数。
Subtask B就是求max(入度为0个数,出度为零个数)。
把每个出度为零的节点连到下一颗树的入度为0的节点上。
代码:
//#include<CSpreadSheet.h> #include<iostream> #include<cmath> #include<cstdio> #include<sstream> #include<cstdlib> #include<string> #include<string.h> #include<cstring> #include<algorithm> #include<vector> #include<map> #include<set> #include<stack> #include<list> #include<queue> #include<ctime> #include<bitset> #include<cmath> #define eps 1e-6 #define INF 0x3f3f3f3f #define PI acos(-1.0) #define ll __int64 #define LL long long #define lson l,m,(rt<<1) #define rson m+1,r,(rt<<1)|1 #define M 1000000007 //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; #define Maxn 110 int low[Maxn],dfn[Maxn],dindex,n; int sta[Maxn],belong[Maxn],bcnt,ss; bool iss[Maxn]; int de1[Maxn],de2[Maxn]; vector<vector<int> >myv; void tarjan(int cur) { //printf(":%d\n",cur); //system("pause"); int ne; dfn[cur]=low[cur]=++dindex; iss[cur]=true; sta[++ss]=cur; for(int i=0;i<myv[cur].size();i++) { ne=myv[cur][i]; if(!dfn[ne]) { tarjan(ne); low[cur]=min(low[cur],low[ne]); } else if(iss[ne]&&dfn[ne]<low[cur]) low[cur]=dfn[ne]; } if(dfn[cur]==low[cur]) { bcnt++; do { ne=sta[ss--]; iss[ne]=false; belong[ne]=bcnt; }while(ne!=cur); } } void solve() { int i; ss=bcnt=dindex=0; memset(dfn,0,sizeof(dfn)); memset(iss,false,sizeof(iss)); for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); while(~scanf("%d",&n)) { myv.clear(); myv.resize(n+1); for(int i=1;i<=n;i++) { int a; while(scanf("%d",&a)&&a) myv[i].push_back(a); } solve(); if(bcnt==1) //本来就是一个强连通分量 { printf("1\n0\n"); continue; } int ansa=0,ansb=0; memset(de1,0,sizeof(de1)); memset(de2,0,sizeof(de2)); for(int i=1;i<=n;i++) { for(int j=0;j<myv[i].size();j++) { int ne=myv[i][j]; if(belong[i]!=belong[ne]) { de1[belong[ne]]++;//入度 de2[belong[i]]++; //出度 } } } for(int i=1;i<=bcnt;i++) { if(!de1[i]) ansa++; if(!de2[i]) ansb++; } ansb=max(ansb,ansa); printf("%d\n%d\n",ansa,ansb); } return 0; }