poj1236 - Network of Schools (强连通图)

来源:互联网 发布:java发邮件添加附件 编辑:程序博客网 时间:2024/06/08 15:33
题目大意:有N个学校,从每个学校都能从一个单向网络到另外一个学校,两个问题
1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。
2:至少需要添加几条边,使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。
解题思路:
首先找连通分量,然后看连通分量的入度为0点的总数,出度为0点的总数,那么问要向多少学校发放软件,就是入度为零的个数,这样才能保证所有点能够找到

然后第二问添加多少条边可以得到使整个图达到一个强连通分量,答案是入度为0的个数和出度为0的个数中最大的

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<cmath>#include<set>#include<vector>#include<map>#include<queue>using namespace std;#define LL long long#define MAX 10000+5const int INF=0x3f3f3f3f;const double inf=1e18;int in[105];int out[105];struct Edge{    int next,to;}edge[50005];int node[MAX];int DFN[MAX];int low[MAX];int instack[MAX];int sstack[MAX];int belong[MAX];int e[105][105];int top;int index;int ecnt;int bcnt;void add_edge(int from,int to){    edge[ecnt].next=node[from];    edge[ecnt].to=to;    node[from]=ecnt++;}void tarjan(int u){    DFN[u]=low[u]=++index;    instack[u]=1;    sstack[++top]=u;    for(int i=node[u];i!=-1;i=edge[i].next){            int v=edge[i].to;            if(!DFN[v]){                tarjan(v);                low[u]=min(low[u],low[v]);            }            else if(instack[v]) low[u]=min(low[u],DFN[v]);    }    if(low[u]==DFN[u]){        bcnt++;        while(1){            int j=sstack[top--];            instack[j]=0;            belong[j]=bcnt;            if(j==u) break;        }    }}int main(){    int n;    scanf("%d",&n);    memset(in,0,sizeof(in));    memset(out,0,sizeof(out));    memset(node,-1,sizeof(node));    memset(instack,0,sizeof(instack));    memset(DFN,0,sizeof(DFN));    memset(low,0,sizeof(low));    memset(belong,0,sizeof(belong));    memset(e,0,sizeof(e));    for(int i=1;i<=n;i++){        int a;        while(scanf("%d",&a)&&a){            add_edge(i,a);            e[i][a]=1;        }    }    top=0;    index=0;    bcnt=0;    for(int i=1;i<=n;i++){        if(!DFN[i]){            tarjan(i);        }    }    for(int i=1;i<=n;i++){        for(int j=1;j<=n;j++){            if(e[i][j]&&belong[i]!=belong[j]){                in[belong[j]]++;                out[belong[i]]++;            }        }    }    int num1=0,num2=0;    for(int i=1;i<=bcnt;i++){        if(!in[i]) num1++;        if(!out[i]) num2++;    }    if(bcnt==1) printf("1\n0\n");    else printf("%d\n%d\n",num1,max(num1,num2));    return 0;}


0 0