posts - 74,  comments - 33,  trackbacks - 0

Network of Schools

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

5
2 4 3 0
4 5 0
0
0
1 0

Sample Output

1
2

Source

IOI 1996
很好的一道题目写了一下Tarjan算法求联通度,没想到的是
#include<cstdio>
#include
<cstring>
#include
<stack>
#include
<vector>
#define MAXN 120
using namespace std;
int pre[MAXN],low[MAXN],id[MAXN];
int cnt,scnt,n,m,k;
vector
<int>v[MAXN];
bool markin[MAXN],markout[MAXN];
stack
<int>ST;
void Tarjan(int x){
    
int t,i;
    
int min=low[x]=pre[x]=cnt++;
    ST.push(x);
    
for(i=0;i<v[x].size();i++){
        t
=v[x][i];
        
if(pre[t]==-1)Tarjan(t);
        
if(low[t]<min)min=low[t];
    }

    
if(min<low[x]){
        low[x]
=min;
        
return;
    }

    
do{
        id[t
=ST.top()]=scnt;
        low[t]
=n;ST.pop();
    }
while(t!=x);
    scnt
++;
}

int SCC(){
    scnt
=cnt=0;
    memset(pre,
0xff,sizeof(pre));
    memset(low,
0,sizeof(low));
    
for(int i=0;i<n;i++)
        
if(pre[i]==-1)Tarjan(i);
    
return scnt;
}

int main(){
    
int i,j,a;
    
while(scanf("%d",&n)!=EOF){
        
for(i=0;i<n;i++)v[i].clear();
        
for(i=0;i<n;i++){
            
while(scanf("%d",&a)&&a)
                v[i].push_back(a
-1);
        }

        k
=SCC();
        memset(markin,
0,sizeof(markin));
        memset(markout,
0,sizeof(markout));
        
int sum_F=0,sum_S=0;
        
for(i=0;i<n;i++)
            
for(j=0;j<v[i].size();j++)
                
if(id[i]!=id[v[i][j]]){
                    markout[id[i]]
=true;
                    markin[id[v[i][j]]]
=true;
                }

        
for(i=0;i<k;i++){
            
if(!markin[i])sum_F++;
            
if(!markout[i])sum_S++;
        }

        printf(
"%d\n",sum_F);
        
if(sum_F==1&&sum_S==1)printf("0\n");
        
else printf("%d\n",sum_F>sum_S?sum_F:sum_S);
    }

}

这样是错的,不知道为什么 ,最后把if(sum_F==1&&sum_S==1)printf("0\n");
改成了if(k==1)printf("0\n");就AC了。实在是不懂为什么呢 ,其实这两个条件应该是等价的
当最后缩成只有一个点的时候必然存在sum_F入度等于出度sum_S等于1。
所以说比较郁闷。。。。
posted on 2009-05-13 16:45 KNIGHT 阅读(185) 评论(1)  编辑 收藏 引用

FeedBack:
# re: Network of Schools
2009-05-14 07:24 | Knight
感谢zju的HH神牛,谢谢 HH神牛的数据2个点 a->b
2
2 0
0
对于in==1&&out==1但是scc==2


  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2009年4月>
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

常用链接

留言簿(8)

随笔档案

文章档案

Friends

OJ

搜索

  •  

最新评论

阅读排行榜

评论排行榜