zoukankan      html  css  js  c++  java
  • poj1236

    来源:http://poj.org/problem?id=1236

    题目大意:给出一个各个学校之间的单向连通图,任务A:求出要令所有学校都收到软件的最小接收学校数目;任务B:求出至少需要添加多少条边,令无论将软件发布到哪一个学校,每一个学校都可以接收到软件

    思路:对单向图求强连通分量,缩点,对于缩点后的图:求出入度为0的缩点个数,这是任务A;求出入度为0和出度为0的缩点个数,取较大的数,这是任务B。

    可能有人问,为什么任务A不是直接求出强连通分量的个数,而是求出入度为0的缩点数呢?因为一个缩点,若入度不为0,则它一定可以从其他缩点得到软件,而不需要发一份给它。对于任务B,则要求添加尽可能少的边,使图成为全连通图,假设有一缩点u,它的出度为0,若将软件发布到这个缩点,则一定不能使得所有学校都收到软件(当然,有一个例外,就是一开始的图就已经是全连通的)。我们需要做的是:将出度为0的缩点全部连接到入度为0的缩点,这样到最后一定可以使得图成为全连通图。因此,对于出度为0和入度为0的缩点个数,取较大的输出就是任务B了。

    注意:当图一开始就是全连通的,应该输出:1  0

    View Code
     1 #include <iostream>
     2 #include <vector>
     3 using namespace std;
     4 
     5 const int maxn=105;
     6 vector <int> a[maxn];
     7 
     8 int n;
     9 int real[maxn],low[maxn],stack[maxn],depth,total,top;
    10 bool instack[maxn];
    11 int color[maxn];
    12 bool f1[maxn],f2[maxn];
    13 
    14 void dfs(int u)
    15 {
    16      int v;
    17      real[u]=low[u]=++depth;
    18      stack[++top]=u;
    19      instack[u]=true;
    20      for (int i=0;i<a[u].size();i++)
    21      {
    22          v=a[u][i];
    23          if (!real[v])
    24          {
    25                       dfs(v);
    26                       low[u]=min(low[u],low[v]);
    27          }
    28          else if (instack[v])
    29               low[u]=min(low[u],real[v]);
    30      }
    31      
    32      if (real[u]==low[u])
    33      {
    34                          total++;
    35                          while (stack[top+1]!=u)
    36                          {
    37                                v=stack[top--];
    38                                color[v]=total;
    39                                instack[v]=false;
    40                          }
    41      }
    42 }
    43 
    44 void tarjan()
    45 {
    46      memset(real,0,sizeof(real));
    47      memset(instack,false,sizeof(instack));
    48      memset(stack,0,sizeof(stack));
    49      depth=total=top=0;
    50      for (int i=1;i<=n;i++)
    51          if (!real[i])
    52             dfs(i);
    53 }
    54 
    55 void solve()
    56 {
    57      if (total==1)
    58      {
    59                   cout<<"1"<<endl<<"0"<<endl;
    60                   return;
    61      }
    62      memset(f1,false,sizeof(f1));
    63      memset(f2,false,sizeof(f2));
    64      for (int i=1;i<=n;i++)
    65      {
    66          for (int j=0;j<a[i].size();j++)
    67              if (color[i]!=color[a[i][j]])
    68              {
    69                                           f1[color[i]]=true;
    70                                           f2[color[a[i][j]]]=true;
    71              }
    72      }
    73      int result1=0,result2=0;
    74      for (int i=1;i<=total;i++)
    75      {
    76          if (!f2[i]) result1++;
    77          if (!f1[i]) result2++;
    78      }
    79      cout<<result1<<endl<<max(result1,result2)<<endl;
    80 }
    81 
    82 int main()
    83 {
    84     cin>>n;
    85     int m;
    86     for (int i=1;i<=n;i++)
    87     {
    88         a[i].clear();
    89         cin>>m;
    90         while (m!=0)
    91         {
    92               a[i].push_back(m);
    93               cin>>m;
    94         }
    95     }
    96     tarjan();
    97     solve();
    98     return 0;
    99 }
  • 相关阅读:
    数据类型装换
    变量及数据类型
    27 网络通信协议 udp tcp
    26 socket简单操作
    26 socket简单操作
    14 内置函数 递归 二分法查找
    15 装饰器 开闭原则 代参装饰器 多个装饰器同一函数应用
    12 生成器和生成器函数以及各种推导式
    13 内置函数 匿名函数 eval,exec,compile
    10 函数进阶 动态传参 作用域和名称空间 函数的嵌套 全局变量
  • 原文地址:https://www.cnblogs.com/ay27/p/2651832.html
Copyright © 2011-2022 走看看