• 求最小点基 poj 1236


    题意:

    在一个信息网络当中,为了能够告知学校最新信息,现在告诉你各个学校之间的联系关系,问你最少能够通知多少个学校就能完成对所有的学校通知完毕,因为具有内在联系的学校会相互通知,若我们现在想要通知其中一个学校就能通过它们内部传递然后就能使所有学校都知道,那么此时我们使某些学校存在一个联系就可以了,问这样的联系我们最少需要创建多少。

    解题思路:只要算出强连通的个数,并且知道哪些强连通没有入度,计数,然后第二个答案只要计数所有强连通入度为0,出度为0的个数,然后取两者最大值,这就是要添加的最少边数。。

    View Code
     1   #include<iostream>
     2   #include<stdio.h>
     3   #define min(a,b) a<b?a:b
     4   #define max(a,b) a>b?a:b
     5   #define S 110
     6   using namespace std;
     7   int n;
     8   int map[S][S],stack[S],dfn[S],low[S],top,Time,exist[S],weight[S],Count,ind[S],outd[S];
     9   void tarjan(int u)
    10   {
    11        dfn[u]=low[u]=++Time;
    12        stack[top++]=u;
    13        exist[u]=1;
    14        for(int to=1;to<=n;to++)
    15        {
    16             if(!dfn[to]&&map[u][to]==1)
    17             {
    18                 tarjan(to);
    19                 low[u]=min(low[u],low[to]);    
    20             }
    21             else
    22             {
    23                 if(map[u][to]==1&&exist[to]==1)
    24                 low[u]=min(low[u],dfn[to]);
    25             }
    26        } 
    27        if(low[u]==dfn[u])
    28        {
    29               Count++;
    30               int v;
    31               do
    32               {
    33                    v=stack[top-1];
    34                    exist[v]=0;
    35                    weight[v]=Count;
    36                    top--;
    37               }while(u!=v);
    38        }
    39   }
    40   int main()
    41   {
    42      int end;
    43      while(scanf("%d",&n)!=EOF)
    44      {
    45         for(int i=1;i<=n;i++)
    46         {
    47             for(int j=1;j<=n;j++)
    48             {
    49              if(i==j)map[i][j]=1;
    50              else
    51              map[i][j]=-1;
    52             }
    53             ind[i]=outd[i]=exist[i]=dfn[i]=low[i]=0;
    54         }
    55         for(int i=1;i<=n;i++)
    56         {
    57             scanf("%d",&end);
    58             while(end)
    59             {
    60                    map[i][end]=1;
    61                    scanf("%d",&end);
    62             }
    63         }
    64         Count=Time=top=0;
    65         for(int i=1;i<=n;i++)
    66         {
    67            if(!dfn[i])
    68               tarjan(i);
    69         }
    70         for(int i=1;i<=n;i++)
    71         {
    72            for(int j=1;j<=n;j++)
    73            {
    74                if(map[i][j]==1&&weight[i]!=weight[j])
    75                {
    76                      ind[weight[j]]++;
    77                      outd[weight[i]]++;                           
    78                }        
    79            }        
    80         }
    81         int max1=0,max2=0;
    82         for(int i=1;i<=Count;i++)
    83         {
    84             if(ind[i]==0)max1++;
    85             if(outd[i]==0)max2++;
    86         }
    87         max2=max(max1,max2);
    88         printf("%d\n",max1);
    89         if(Count==1)printf("0\n");
    90         else
    91         printf("%d\n",max2); 
    92      } 
    93      return 0;    
    94   }
  • 相关阅读:
    java内存回收机制
    scala学习
    [java实现]找一个数组的最大和的连续子数组(时间复杂度 O(n))
    linux 进程的创建
    linux中的进程和线程
    linux 文件系统
    gdb 调试程序
    makefile
    linux下的gcc编译器
    socket 网络编程
  • 原文地址:https://www.cnblogs.com/nuoyan2010/p/2667112.html
Copyright © 2020-2023  润新知