USACO Training 5.3.3 Network of Schools 校园网 题解与分析

来源:互联网 发布:tcp延迟确认算法 编辑:程序博客网 时间:2024/06/05 17:36

Network of Schools 校园网

IOI '96 Day 1 Problem 3

描述

一些学校连入一个电脑网络。那些学校已订立了协议:每个学校都会给其它的一些学校分发软件(称作“接受学校”)。注意即使 B 在 A 学校的分发列表中, A 也不一定在 B 学校的列表中。

你要写一个程序计算,根据协议,为了让网络中所有的学校都用上新软件,必须接受新软件副本的最少学校数目(子任务 A)。更进一步,我们想要确定通过给任意一个学校发送新软件,这个软件就会分发到网络中的所有学校。为了完成这个任务,我们可能必须扩展接收学校列表,使其加入新成员。计算最少需要增加几个扩展,使得不论我们给哪个学校发送新软件,它都会到达其余所有的学校(子任务 B)。一个扩展就是在一个学校的接收学校列表中引入一个新成员。

格式

PROGRAM NAME: schlnet

INPUT FORMAT 输入文件的第一行包括一个整数 N:网络中的学校数目(2 <= N <= 100)。学校用前 N 个正整数标识。接下来 N 行中每行都表示一个接收学校列表(分发列表)。第 i+1 行包括学校 i 的接收学校的标识符。每个列表用 0 结束。空列表只用一个 0 表示。

OUTPUT FORMAT

你的程序应该在输出文件中输出两行。第一行应该包括一个正整数:子任务 A 的解。第二行应该包括子任务 B 的解。

SAMPLE INPUT (file schlnet.in)

52 4 3 04 5 0001 0


SAMPLE OUTPUT (file schlnet.out)

12
【分析】:Tarjan算法求强连通分量。
   方法:首先,用链表构图,然后Tarjan求分量,并记录各个点是属于哪个强连通分量,然后枚举每条边,若该边的出发点i和到达点j不在同一强连通分量中(即从出发点所属强连通分量的任意一点出发均不能到达点j),就将i的强连通分量出度+1,j的强连通分量的入度+1<这里实际是将每个强连通分量看成一个点来处理>,则第一问的答案就是入度为0的强连通分量个数<只有这些强连通分量中的学校无法从其他学校得到软件>。第二问答案为max(入度为0的强连通分量个数,出度为0的强连通分量个数<即无法从该强连通分量传出软件>),根据题意,相当于是将若干个强连通分量要合为一个强连通分量,即满足题意“不论我们给哪个学校发送新软件,它都会到达其余所有的学校”,这样的强连通分量性质为至少有一个出度和入度。第二问答案解释完毕.最后须注意的是,若用Tarjan求出的只有一个强连通分量,就应特判,直接输出1和0
【代码】:
/*   ID:csyzcyj1   PROG:schlnet   LANG:C++*/#include<stdio.h>#include<string.h>#include<stdlib.h>#include<algorithm>#include<iostream>#include<vector>#include<queue>using namespace std;#define MAX 101#define MAXN 100001struct edge{int to,next,from;};edge a[MAXN];int N,tot=0,last[MAX],step=0,stack[MAXN],tot1=0,num=0,belong[MAX],indegree[MAX],outdegree[MAX];int DFN[MAX],LOW[MAX],IN=0,OUT=0;bool instack[MAX],vis[MAX];void add(int x,int y)//链表构图 {      a[++tot].to=y;      a[tot].from=x;      a[tot].next=last[x];      last[x]=tot;}void tarjan(int now){      DFN[now]=LOW[now]=++step;      stack[++tot1]=now;      instack[now]=true;      for(int i=last[now];i;i=a[i].next)      {            int now_to=a[i].to;            if(!DFN[now_to])            {                  tarjan(now_to);                  LOW[now]=min(LOW[now],LOW[now_to]);            }            else if(instack[now_to])                  LOW[now]=min(LOW[now],DFN[now_to]);      }      if(DFN[now]==LOW[now])      {            num++;            int now_out;            do            {                  now_out=stack[tot1--];                  instack[now_out]=false;                  belong[now_out]=num;            }while(now_out!=now);      }}int main(){      freopen("schlnet.in","r",stdin);  freopen("schlnet.out","w",stdout);   memset(instack,false,sizeof(instack));  memset(vis,false,sizeof(vis));  scanf("%d",&N);  for(int i=1;i<=N;i++)  {            int A;            while(scanf("%d",&A)!=EOF && A!=0)            {                  add(i,A);            }      }      for(int i=1;i<=N;i++)            if(!DFN[i])                  tarjan(i);      for(int i=1;i<=tot;i++)      {            if(belong[a[i].from]!=belong[a[i].to])            {                  outdegree[belong[a[i].from]]++;                  indegree[belong[a[i].to]]++;                          }      }      if(num==1)   {printf("1\n0\n");return 0;}//特判:当只有一个强连通分量时       for(int i=1;i<=num;i++)      {            IN=indegree[i]==0 ? IN+1 : IN;            OUT=outdegree[i]==0 ? OUT+1 : OUT;      }      printf("%d\n%d\n",IN,max(IN,OUT));  //system("pause");      return 0;}
转载注明出处:http://blog.csdn.net/u011400953
原创粉丝点击