poj1236 Network of Schools

来源:互联网 发布:js获取数组索引值 编辑:程序博客网 时间:2024/05/29 09:59

链接:http://poj.org/problem?id=1236

题意:有一个由若干个学校组成的网络。每个学校与其相连(有向边)的学校构成一个“receiving schools”,即这个学校

可以发送文件至这些“receiving schools”。有一个A任务:最少需要几份原文件,使得每个人都能接收到文件。B任务:最

少添加几条边,使得无论从哪一个学校发送原文件,使得每个学校都能收到文件。


A任务:有向图求连通分量,然后缩点,求每个缩点的入度。所有缩点中,入度为零的点即为所需的原文件数(即这些学校

必须发一份原文件,否则不能保证每个学校都能收到文件)。

B任务:求出连通分量后,缩点,添加边使其变成强连通图。计算每个缩点的出度和入度。记出度为0的缩点个数为outd,入度为0的缩点个数为ind。

则,所需添加的边的数目为max(ind,outd)。


#include<cstdio>#include<cstring>#define MAXN 105#define MAX(a,b) a>b?a:busing namespace std;struct Edge{   int to;   int next;}edge[MAXN*MAXN];int head[MAXN],dfn[MAXN],low[MAXN];int degree[MAXN][2],belong[MAXN],stack[MAXN],instack[MAXN];int index,bcnt,ecnt,top;int n;void add(int u,int v){    edge[ecnt].to=v;edge[ecnt].next=head[u];head[u]=ecnt++;}void tarjan(int u){int i,v;dfn[u]=low[u]=++index;stack[top++]=u;instack[u]=1;for(i=head[u];i!=-1;i=edge[i].next){v=edge[i].to;if(!dfn[v]){tarjan(v);if(low[u]>low[v])low[u]=low[v];}else if(instack[v]&&low[u]>dfn[v])low[u]=dfn[v];}if(dfn[u]==low[u]){bcnt++;do{v=stack[--top];instack[v]=0;belong[v]=bcnt;}while(u!=v);}}int main(){int a,b;int ind,outd;    while(scanf("%d",&n)!=EOF)    {memset(head,-1,sizeof(head));memset(dfn,0,sizeof(dfn));memset(instack,0,sizeof(instack));memset(degree,0,sizeof(degree));ecnt=index=bcnt=top=0;for(a=1;a<=n;a++)while(scanf("%d",&b),b)    add(a,b);    for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);for(int i=1;i<=n;i++)for(int j=head[i];j!=-1;j=edge[j].next)if(belong[i]!=belong[edge[j].to]){    degree[belong[i]][0]++;degree[belong[edge[j].to]][1]++;}ind=outd=0;for(int i=1;i<=bcnt;i++){if(degree[i][0]==0)outd++;if(degree[i][1]==0)ind++;}int max=MAX(ind,outd);if(bcnt==1)max=0;//如果连通块只有一个,则加入0条边printf("%d\n",ind);printf("%d\n",max);    }}


0 0
原创粉丝点击