poj 1236

来源:互联网 发布:centos png 编辑:程序博客网 时间:2024/06/05 09:53
这个题目有点难懂 , (Subtask A)和(Subtask B)是表示两个任务 , 就是两个问题 。
A:求出最少给几个点发送软件 , 才能让所有点都能得到这个软件。
B:在建成的图中 , 最少要增加几条边 ,才能让其变成一个强连通图 。

解法:
A:先求出所有强连通分量 , 然后再用这些分量去建一个图 , 图中入度为0的点 , 就是要发送软件的点 。

代码:
#include
#include
#include
#include
#include
#include
using namespace std;

const int MAXN = 200 ;
vectorgrap[MAXN] , scc[MAXN];
int pre[MAXN] , lowlink[MAXN] , sccno[MAXN];
int n , dfs_clock , scc_cnt;
stacks;

void init()
{
    for(int i =1 ; i <= n; i++)
    {
      grap[i].clear();
      scc[i].clear();
    }
}

void dfs(int u)  // 寻找强连通分量
{
    lowlink[u] =pre[u] = ++dfs_clock;
   s.push(u);
    for(int i =0 ; i < grap[u].size() ; i++)
    {
       int v =grap[u][i];
      if(!pre[v])
       {
         dfs(v);
         if(lowlink[u] > lowlink[v])  lowlink[u] =lowlink[v];
       }
       elseif(!sccno[v] && lowlink[u] > pre[v])
          lowlink[u] =pre[v];
    }
   if(lowlink[u] == pre[u])
    {
      scc_cnt++;
       for(;;)
       {
          int x =s.top() ; s.pop();
          sccno[x] =scc_cnt;
          if(x ==u)  break;
       }
    }
}

void find_scc()
{
    memset(pre,0 , sizeof(pre));
    memset(sccno, 0 , sizeof(sccno));
    dfs_clock =scc_cnt = 0;
    for(int i =1; i <= n; i++)
      if(!pre[i])  dfs(i);
}



int main()
{
   while(scanf("%d" , &n ) != EOF)
    {
      init();
       int i , x ,y , j;
       for(i = 1 ;i <= n; i++)
       {
          for(; ;)
          {
             scanf("%d" ,&x);
             if(x ==0)  break;
            grap[i].push_back(x);
          }
       }
      find_scc();
       intchu_du[MAXN] ,ru_du[MAXN];  
      memset(chu_du , 0 , sizeof(chu_du) );
       memset(ru_du, 0 , sizeof(ru_du));
       for(i = 1; i<= n; i++)
          for(j = 0 ;j < grap[i].size();  j++)
          {
             int v =grap[i][j];
             x = sccno[i]; 
             y =sccno[v];
             if(x !=y) 
             {
               scc[x].push_back(y);
               ru_du[y]++;
               chu_du[x]++;
             }
          }
        
       x = 0 , y =0;
       for(i = 1; i<= scc_cnt ; i++)
       {
         if(!chu_du[i])  x += 1;
         if(!ru_du[i])  y += 1;
       }
       x =x>y?x:y;
       if(scc_cnt== 1) {y = 1; x = 0;}
      printf("%d\n" , y);
       printf("%d\n" , x);
    }
    return0;
}
0 0