poj1236Network of Schools_强连通分量缩点(tarjan算法解决)

来源:互联网 发布:货运平台软件下载 编辑:程序博客网 时间:2024/05/17 07:07

poj1236题目链接

题目大意:有N个学校,从每个学校都能从一个单向网络到另外一个学校,两个问题
1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。
2:至少需要添加几条边,使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。(就是最少加入几条边,让这个图变成强连通图)

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

但是当连通分量为1的时候,就直接输入1,0,因为如果Bcnt==1的时候这个图就是一个强连通图了就不需要加边了。

主要就是tarjan算法了,这个算法的注释可以看(点这里)

/*Sample Input52 4 3 04 5 0001 0Sample Output12*/

#include<stdio.h>#include<vector>#include<stack>#include<string.h>using namespace std;#define max(a,b) a>b?a:b#define min(a,b) a<b?a:bint in[105];int out[105];int dfn[105];int low[105];int Belong[105];int time=0,Bcnt=0;bool in_S[105];int n;vector<int>e[105];stack<int>S; void tarjan(int u){int i,v;S.push(u);in_S[u]=true;dfn[u]=low[u]=++time;for(i=0;i<e[u].size();i++){v=e[u][i];if(!dfn[v]){tarjan(v);low[u]=min(low[u],low[v]);}else if(in_S[v]){low[u]=min(low[u],dfn[v]);}}if(dfn[u]==low[u]){Bcnt++;do{v=S.top();S.pop();in_S[v]=false;Belong[v]=Bcnt;}while(v!=u); }}int main(){int i,j,v;   scanf("%d",&n);     for(i=1;i<=n;i++)    {        while(scanf("%d",&v)&&v)       {   e[i].push_back(v);       }        }        for(i=1;i<=n;i++)    {    if(!dfn[i])      tarjan(i);    }     if(Bcnt==1){printf("1\n0\n");return 0;}     for(i=1;i<=n;i++)      for(j=0;j<e[i].size();j++)      {      v=e[i][j];      if(Belong[i]!=Belong[v])        {        in[Belong[v]]++;        out[Belong[i]]++;        }      }          int num=0,num1=0;       for(i=1;i<=Bcnt;i++)    {    if(in[i]==0)      num++;    if(out[i]==0)      num1++;    }    printf("%d\n%d\n",num,max(num,num1));return 0;}




0 0
原创粉丝点击