poj 1236

来源:互联网 发布:jquery.js文件下载 编辑:程序博客网 时间:2024/06/05 08:27

题目大意:

    一些学校连成了网络, 在学校之间存在某个协议:每个学校都维护一张传送表,表明他们要负责将收到的软件传送到表中的所有学校。如果A在B的表中,那么B不一定在A的表中。

    现在的任务就是,给出所有学校及他们维护的表,问1、如果所有学校都要被传送到,那么需要几份软件备份;2、如果只用一份软件备份,那么需要添加几条边?

思路:首先找连通分量,然后看连通分量的入度为0点的总数,出度为0点的总数,那么问要向多少学校发放软件,就是入度为零的个数,这样才能保证所有点能够找到
然后第二问添加多少条边可以得到使整个图达到一个强连通分量,答案是入度为0的个数和出度为0的个数中最大的





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 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

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

52 4 3 04 5 0001 0

Sample Output

12


 #include<stdio.h>#include<string.h>#include<math.h>#include<stack>#include<vector>#include<iostream>#define MAX 110using namespace std;int vis[MAX];int belong[MAX];//记录节点属于哪一个强连通分量int dfn[MAX],low[MAX];vector<int>gra[MAX];stack<int>s;int index;int count1;//记录强连通分量的个数及编号int out[MAX],in[MAX];int n,m;void tarjan(int pos){    int i;//在i若定义成全局变量就wa,为保险起见 若函数内部和main函数用到同样的变量名(如i)在函数内部和main函数分别定义    dfn[pos]=low[pos]=++index;    vis[pos]=1;    s.push(pos);    for(i=0;i<gra[pos].size();i++)    {        int next=gra[pos][i];        if(!dfn[next])        {            tarjan(next);            low[pos]=min(low[pos],low[next]);        }        else        if(vis[next]==1)        {            low[pos]=min(low[pos],dfn[next]);        }    }    if(dfn[pos]==low[pos])    {        count1++;        while(1)        {            int t=s.top();            belong[t]=count1;            vis[t]=0;//说明已经不在栈内            s.pop();                        if(t==pos)            break;        }    }}int main(){    int a;    int i,j;    int ans2;    while(scanf("%d",&n)!=EOF)    {        memset(vis,0,sizeof(vis));        memset(dfn,0,sizeof(dfn));        memset(low,0,sizeof(low));        memset(belong,0,sizeof(belong));         for(i=0;i<MAX;i++)        {            gra[i].clear();        }        while(!s.empty())        {            s.pop();        }        for(i=1;i<=n;i++)        {            while(scanf("%d",&a),a)            {                gra[i].push_back(a);            }        }        index=count1=0;//初始化不能忘        for(i=1;i<=n;i++)        {            if(!dfn[i])            {                tarjan(i);            }        }        memset(out,0,sizeof(out));        memset(in,0,sizeof(in));        for(i=1;i<=n;i++)        {            for(j=0;j<gra[i].size();j++)            {                if(belong[i]!=belong[gra[i][j]])//两个点不属于同一个强连通分量                {                    out[belong[i]]++;                    in[belong[gra[i][j]]]++;                }            }        }        int out1=0;        int in1=0;        for(i=1;i<=count1;i++)        {            if(out[i]==0)            {                out1++;            }             if(in[i]==0)            {                in1++;            }        }        if(count1==1)        printf("1\n0\n");        else{        ans2=max(out1,in1);        printf("%d\n",in1);        printf("%d\n",ans2);        }    }}


0 0
原创粉丝点击