POJ 1236

来源:互联网 发布:网络电视能接有线吗 编辑:程序博客网 时间:2024/06/05 05:56
 


 

题号:POJ 1236

题意描述:

网络中有一些学校,每个学校可以分发软件给其他学校。可以向哪个分发取决于他们各自维护的一个清单。

两个问题

1:至少要copy多少份新软件给那些学校, 才能使得每个学校都能得到。

2:要在所有的学校的清单里面至少一共增加几项才能 使得把软件给任意一个学校,所有的学校都能收得到。

算法:

第一问的算法非常简单,先求SCC后(本人用的是Tarjan)缩点,求出所有的入度为0的点的个数即为届。

第二问在第一问的基础上,答案即为<入度为0的点的个数>和<出度为0的点的个数>之间的最大值,求证明。

第二问有一个特例,如果该图本来就强联通(也就是说缩点后的图只有一个点),那么答案就是0而非1。

DA:SCC、缩点、强联通、Tarjan

Accepted

 

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;int G[101][101];int low[101],indx[101],belong[101],g[101];int instack[101],stack[101];int g1[101][101],G1[101][101];int gin[101],gout[101],gc[101];int cnt,n,nm,top,ans;void Tarjan(int i){     indx[i]=++nm;     low[i]=nm;     instack[i]=1;     stack[++top]=i;          for (int k=1;k<=g[i];k++){         int j=G[i][k];         if (indx[j]){            if (instack[j]) low[i]=min(low[i],indx[j]);         }         else         {             Tarjan(j);             low[i]=min(low[i],low[j]);         }     }          if (low[i]==indx[i]){        ++cnt;int j;        do{              j=stack[top--];              instack[j]=0;              belong[j]=cnt;        }while (i!=j);     }}int find(){    for (int i=1;i<=n;i++){        for (int k=1;k<=g[i];k++){            int j=G[i][k];            int i1=belong[i];            int j1=belong[j];            if (!g1[i1][j1] && i1!=j1){                             g1[i1][j1]=1;                             G1[i1][++gc[i1]]=j1;                             gin[j1]++;gout[i1]++;            }        }    }    int ans1=0;int ans2=0;    for (int i=1;i<=cnt;i++){        if (gin[i]==0) ans1++;        if (gout[i]==0) ans2++;    }    ans=max(ans1,ans2);    if (cnt==1) ans=0;     return ans1;}int main(){    scanf("%d",&n);    int x1;    for (int i=1;i<=n;i++){        while (scanf("%d",&x1)!=EOF){              if (x1==0) break;              G[i][++g[i]]=x1;        }    }        for (int i=1;i<=n;i++)        if (!indx[i]) Tarjan(i);        printf("%d\n",find());    printf("%d\n",ans);}    

原创粉丝点击