zoukankan      html  css  js  c++  java
  • hdu--3836--tarjan+缩点

    缩点 很简单的啊... 就是将原来一个连通块变成一个点..

    可能你原本是这样的  A->B->C->A  缩点完成后 我们就把{A,B,C}用数字1来表示 如果还有D->E->D 那我们再讲{D,E}用2表示....

    最后的sum就是代表连通块总的个数

    然后 一般 缩点完成后 我们现在得到了n个连通块 我们要考虑的是 最少需要添加几条边来把它串联起来

    这样考虑

    假如给你2个点   A B 想要让他们联通 需要在他们之间建立两条边 分别是A->B   B->A 你会发现这样 A B的入度 出度分别从0变成了1

    如果是这样的情况 那么 现在A的出度为2 入度为0   B和C的出度为0 入度为1 我们只需要B->A  C->A建立边就可以了

    这样我们就能达到B C的出度增加 A的入度增加

    其实 是因为 在任何一个连通图中每个点的入度和出度都是>=1这样才能达到让别人联向自己 自己通向别人

    所以 我们只需要求出在缩点完成后的图中   入度为0 与 出度为0的点的个数大小就可以了  取大的

    ******************

    如果是做题的话 有一点要小心 很容易WA在这里..不能直接判断max(in,out)来输出 而是首先判断缩点后的图 是不是连通图 是的话就直接输出0了 如果直接输出max(in,out)就是1了.......

      1 #include <iostream>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <stack>
      5 using namespace std;
      6 
      7 int n , cnt , index , sum;
      8 const int size = 20010;
      9 struct data
     10 {
     11     int st;
     12     int end;
     13 }node[size*3];
     14 struct graph
     15 {
     16     int to;
     17     int next;
     18 }edge[size*3];
     19 int head[size];
     20 int father[size];
     21 int No[size];
     22 int scc[size];
     23 int in[size];
     24 int out[size];
     25 bool vis[size];
     26 stack<int>s;
     27 
     28 void init( )
     29 {
     30     memset( head , -1 , int*sizeof(n+10) );
     31     memset( No , 0 , int*sizeof(n+10) );
     32     memset( father , 0 , int*sizeof(n+10) );
     33     memset( vis , false , int*sizeof(n+10) );
     34     memset( scc , 0 , int*sizeof(n+10) );
     35     memset( in , 0 , int*sizeof(n+10) );
     36     memset( out , 0 , int*sizeof(n+10) );
     37 }    
     38 
     39 void add( int st , int end )
     40 {
     41     edge[cnt].to = end;
     42     edge[cnt].next = head[st];
     43     head[st] = cnt ++;
     44 }
     45 
     46 void tarjan( int u )
     47 {
     48     int v , temp;
     49     No[u] = father[u] = index++;
     50     vis[u] = true;
     51     s.push(u);
     52     for( int i = head[u] ; ~i ; i = edge[i].next )
     53     {
     54         v = edge[i].to;
     55         if( !No[v] )
     56         {
     57             tarjan(v);
     58             father[u] = min( father[u] , father[v] );
     59         }
     60         else if( vis[v] )
     61         {
     62             father[u] = min( father[u] , No[v] );
     63         }
     64     }
     65     if( father[u] == No[u] )
     66     {
     67         sum ++;
     68         while(1)
     69         {
     70             temp = s.top();
     71             s.pop();
     72             vis[temp] = false;
     73             scc[temp] = sum;
     74             if( father[temp] == No[temp] )
     75                 break;
     76         }
     77     }
     78 }
     79 
     80 int main()
     81 {
     82     cin.sync_with_stdio(false);
     83     int m , st , end , inMax , outMax;
     84     while( cin >> n >> m )
     85     {
     86         inMax = outMax = cnt = sum = 0;
     87         index = 1;
     88         init();
     89         for( int i = 0 ; i<m ; i++ )
     90         {
     91             cin >> st >> end;
     92             add( st , end );
     93             node[i].st = st;
     94             node[i].end = end;
     95         }
     96         for( int i = 1 ; i<=n ; i++ )
     97         {
     98             if( !No[i] )
     99                 tarjan(i);
    100         }
    101         for( int i = 0 ; i<m ; i++ )
    102         {
    103             if( scc[ node[i].st ]!=scc[ node[i].end ] )
    104             {
    105                 out[ scc[node[i].st] ] ++;
    106                 in[ scc[node[i].end] ] ++;
    107             }
    108         }
    109         for( int i = 1 ; i<=sum ; i++ )
    110         {
    111             if( !in[i] )
    112                 inMax ++;
    113             if( !out[i] )
    114                 outMax ++;
    115         }
    116         if( sum==1 )
    117             cout << "0" << endl;
    118         else
    119             cout << max( inMax , outMax ) << endl;
    120     }
    121     return 0;
    122 }
    View Code


    因为 这里的数组要开的TM的实在是太多了 所以我用了 (n)*sizeof(int)来初始化 我测了下 节约了15ms....

    today:

      后来我终于知道

      它并不是我的花

      我只是恰好途径了它的盛放

    just follow your heart
  • 相关阅读:
    caffe绘制训练过程的loss和accuracy曲线
    ROC曲线和PR曲线
    Lintcode--009(单词切分)
    已知有字符串foo=”get-element-by-id”,写一个function将其转化成驼峰表示法”getElementById”
    web前端性能优化汇总
    Restful风格的前后端分离
    渐进式 JPEG (Progressive JPEG)来提升用户体验
    ESLint检测JavaScript代码
    JavaScript对象浅复制
    JavaScript对象深复制
  • 原文地址:https://www.cnblogs.com/radical/p/3931749.html
Copyright © 2011-2022 走看看