POJ 1236 Network of Schools —— (缩点的应用)

Posted Storm_Spirit

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1236 Network of Schools —— (缩点的应用)相关的知识,希望对你有一定的参考价值。

  题目大意:有N个学校和一些有向边将它们连结,求:

    1.最少需要向几个学校发放软件,使得他们中的每一个学校最终都能够获得软件。

    2.最少需要增加几条有向边使得可以从任意一个学校发放软件,使得每一个学校最终都能够获得软件。

  分析:

    1.缩点以后,找出入度为0的点的个数即可(因为没人可以给他们软件)。

    2.缩点以后,答案即是max(入度为0的点,出度为0的点)。因为只要另每一对入度为0和出度为0的点相连接即可。

  第二个问题也有无向图的版本,那样的话处理方法是:缩点以后,找出那些度为1的点,个数为cnt,向上整除2即可(即答案为(cnt+1)/2)。

  代码如下:

  1 #include <stdio.h>
  2 #include <stack>
  3 #include <algorithm>
  4 #include <string.h>
  5 #include <vector>
  6 using namespace std;
  7 
  8 const int N = 100+5;
  9 
 10 stack<int> S;
 11 int scc_cnt;  //强连通分量的个数
 12 int dfs_clock;    //访问到该节点的时间戳
 13 int belong[N];  //belong[i]表示i节点所属于第几个强连通分量
 14 int dfn[N];     //表示第i个节点被访问的时间
 15 int low[N];    //表示第i个节点的子节点所能访问到的最小的dfn值
 16 vector<int> G[N];
 17 int in[100+5],out[100+5];
 18 
 19 void dfs(int u)
 20 {
 21     dfn[u] = low[u] = ++dfs_clock;
 22     S.push(u);
 23     for(int i=0;i<G[u].size();i++)
 24     {
 25         int v = G[u][i];
 26         if(!dfn[v])
 27         {
 28             dfs(v);
 29             low[u] = min(low[u],low[v]);
 30         }
 31         else if(!belong[v])
 32         {
 33             low[u] = min(low[u],low[v]);
 34         }
 35     }
 36     if(low[u]==dfn[u])
 37     {
 38         scc_cnt++;
 39         for(;;)
 40         {
 41             int x = S.top();S.pop();
 42             belong[x] = scc_cnt;
 43             if(x==u) break;
 44         }
 45     }
 46 }
 47 
 48 void scc(int n)
 49 {
 50     memset(dfn,0,sizeof(dfn));
 51     memset(belong,0,sizeof(belong));
 52     dfs_clock = scc_cnt = 0;
 53     for(int i=1;i<=n;i++)
 54     {
 55         if(!dfn[i]) dfs(i);
 56     }
 57 }
 58 
 59 int main()
 60 {
 61     int n;
 62     while(scanf("%d",&n)==1)
 63     {
 64         memset(in,0,sizeof(in));
 65         memset(out,0,sizeof(out));
 66         for(int i=1;i<=n;i++) G[i].clear();
 67         for(int i=1;i<=n;i++)
 68         {
 69             int to;
 70             while(scanf("%d",&to)==1&&to)
 71             {
 72                 G[i].push_back(to);
 73             }
 74         }
 75         
 76         scc(n);
 77         if(scc_cnt==1)
 78         {
 79             puts("1\n0");
 80             continue;
 81         }
 82         for(int i=1;i<=n;i++)
 83         {
 84             for(int j=0;j<G[i].size();j++)
 85             {
 86                 int v = G[i][j];
 87                 if(belong[i]==belong[v]) continue;
 88                 in[belong[v]]++;
 89                 out[belong[i]]++;
 90             }
 91         }
 92         int incnt=0,outcnt=0;
 93         for(int i=1;i<=scc_cnt;i++)
 94         {
 95             if(!in[i]) incnt++;
 96             if(!out[i]) outcnt++;
 97         }
 98         printf("%d\n%d\n",incnt,max(incnt,outcnt));
 99     }
100     return 0;
101 }

 

以上是关于POJ 1236 Network of Schools —— (缩点的应用)的主要内容,如果未能解决你的问题,请参考以下文章

poj1236Network of Schools Tarjan裸题

[POJ1236]Network of Schools(并查集+floyd,伪强连通分量)

POJ1236Network of Schools(强连通分量 + 缩点)

POJ 1236 Network of Schools —— (缩点的应用)

POJ 1236 Network of Schools(tarjan算法 + LCA)

poj1236 Network of Schools Tarjian算法