POJ 1236 Network of Schools 强连通分量+缩点

来源:互联网 发布:mac 网线转接头 编辑:程序博客网 时间:2024/05/04 15:51

点击打开链接

 

 

Network of Schools
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 8941 Accepted: 3526

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

Source

IOI 1996

 

 

题意:络中的一学校可以将软件发送给其他一些学校,能够发送给谁取决于他们各自维护的一个清单。将学校看成一个节点,给出每个学校的维护清单,问至少需要复制几次软件,使毎个学校都能够得到该软件,在清单中至少添加几项,可使软件至少复制一次,所有学校都可以得到。

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

#include<stdio.h>#include<string.h>#define MAX 107#define min(a,b) (a<b?a:b)#define max(a,b) (a>b?a:b)int low[MAX],dfn[MAX],map[MAX][MAX],indegree[MAX],outdegree[MAX];int stack[MAX];bool vis[MAX];int belong[MAX];int n,cnt,top,count;void init(){    cnt=top=count=0;    memset(vis,false,sizeof(vis));    memset(map,0,sizeof(map));    memset(dfn,0,sizeof(dfn));    //memset(low,0,sizeof(low));    memset(indegree,0,sizeof(indegree));    memset(outdegree,0,sizeof(outdegree));}void tarjan(int x){    int i;    dfn[x]=low[x]=++cnt;    stack[top++]=x;    vis[x]=true;    for(i=1;i<=n;i++)    {        if(!map[x][i])continue;        if(!dfn[i])        {            tarjan(i);            low[x]=min(low[x],low[i]);        }        else if(vis[i])        {            low[x]=min(low[x],dfn[i]);        }    }    if(low[x]==dfn[x])    {        count++;        int tmp;        while(1)        {            tmp=stack[--top];            belong[tmp]=count;            vis[tmp]=false;            if(tmp==x)break;        }    }}void output(){    int i,j,inde=0,outde=0;    for(i=1;i<=n;i++)//找强连通分量的入度和出度    for(j=1;j<=n;j++)    {        if(map[i][j]&&belong[i]!=belong[j])        {            indegree[belong[j]]++;            outdegree[belong[i]]++;        }    }    for(i=1;i<=count;i++)//求入度和出度为0的点的个数    {        if(!indegree[i])inde++;        if(!outdegree[i])outde++;    }    if(count==1)    printf("1\n0\n");    else    printf("%d\n%d\n",inde,max(inde,outde));}int main(){    while(scanf("%d",&n)!=EOF)    {        int i,j,a;        init();        for(i=1;i<=n;i++)        {            while(scanf("%d",&a),a)            map[i][a]=1;        }        for(i=1;i<=n;i++)        {            if(!dfn[i])            tarjan(i);        }        output();    }    return 0;}