[POJ 1236][IOI 1996]Network of Schools
Description
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
Output
Sample Input
5 2 4 3 0 4 5 0 0 0 1 0
Sample Output
1 2
Source
题目大意:给定一个有向图,求至少要有多少个点, 才能从这些点出发到达所有点;至少要添加多少条边,才能从任意一点出发到达所有点
首先要推出一个定理:在DAG中,对于所有入度不为0的点,一定有入度为0的点可达(因为从入度为0的点倒着走,一定能走到入度不为0的点)
于是此题可用tarjan缩点,求有多少个入度为0的点,这就是第一个问题的答案。
第二个问题的答案为入度为0的点和出度为0的点的最小值,证明比较难,略。
对于这道题,因为只要求入度和出度为0的点,故只需在tarjan过程中记录每个点归属哪个强连通分量,然后统计输出即可
#include <iostream> #include <stdio.h> #include <string.h> #define MAXE 500 #define MAXV 3000 using namespace std; int N; struct edge { int u,v,next; }edges[MAXV]; int head[MAXE],nCount=0; int dfn[MAXE],low[MAXE],index=0; int belong[MAXE],tot=0; //belong[i]=i点所属的强连通分量,tot=强连通分量总数 bool inStack[MAXE]; int stack[MAXE*4],top=0; bool map[MAXE][MAXE]; int inDegree[MAXE],outDegree[MAXE],inZero=0,outZero=0; //入度,出度 int max(int a,int b) { if(a>b) return a; return b; } int min(int a,int b) { if(a<b) return a; return b; } void AddEdge(int U,int V) { edges[++nCount].u=U; edges[nCount].v=V; edges[nCount].next=head[U]; head[U]=nCount; } void tarjan(int u) { dfn[u]=low[u]=++index; stack[++top]=u; //该点入栈 inStack[u]=true; for(int p=head[u];p!=-1;p=edges[p].next) { int v=edges[p].v; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(inStack[v]) { low[u]=min(low[u],dfn[v]); } } int v; if(dfn[u]==low[u]) { tot++; do { v=stack[top--]; belong[v]=tot; inStack[v]=false; } while(u!=v); } } int main() { int to; cin>>N; memset(head,-1,sizeof(head)); for(int i=1;i<=N;i++) { while(1) { cin>>to; if(to==0) break; AddEdge(i,to); map[i][to]=true; } } for(int i=1;i<=N;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) { if(map[i][j]&&belong[i]!=belong[j]) { inDegree[belong[j]]++; outDegree[belong[i]]++; } } for(int i=1;i<=tot;i++) { if(!inDegree[i]) inZero++; if(!outDegree[i]) outZero++; } if(tot==1) cout<<1<<endl<<0<<endl; else cout<<inZero<<endl<<max(inZero,outZero)<<endl; return 0; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。