HDU1827 (tarjan+缩点)

  因为可以通过其他人来通知他们认识的人,所以这幅图可以用强连通分量变成一个

  缩点的图,所有相互强连通分支变成一个缩点,求的所有缩点中入度为0的缩点即为
所求的需要通知的最小人数。然后再枚举所有人所在的缩点是否入度为0,是的话更 新该缩点所需的最小费用即可

 

View Code
  1 #include<stdio.h>

  2 #include<string.h>

  3 #include<stdlib.h>

  4 #include<stack>

  5 #include<algorithm>

  6 using namespace std;

  7 const int maxn = 1005;

  8 const int maxm = 2005;

  9 const int inf =999999;

 10 struct node{

 11     int v,u,next;

 12 }edge[ maxm ];

 13 int head[ maxn ],cnt;

 14 int vis[ maxn ],low[ maxn ],dfn[ maxn ],id; 

 15 int n,m,ans1;//ans1:缩点的个数( from 1 to ans1 )

 16 int cost[ maxn ];

 17 int belong[ maxn ],inde[ maxn ];//缩点,入度

 18 stack<int>q;

 19 void init(){

 20     cnt=0;

 21     id=0;

 22     ans1=0;

 23     memset( vis,0,sizeof( vis ));

 24     memset( dfn,-1,sizeof(dfn) );

 25     memset( low,-1,sizeof( low ));

 26     memset( head,-1,sizeof( head ));

 27 }

 28 void addedge( int a,int b ){

 29     edge[ cnt ].v=a;

 30     edge[ cnt ].u=b;

 31     edge[ cnt ].next=head[ a ];

 32     head[ a ]=cnt++;

 33 }

 34 void tarjan( int now ){

 35     dfn[ now ]=low[ now ]=id++;

 36     vis[ now ]=1;

 37     q.push( now );

 38     for( int i=head[ now ];i!=-1;i=edge[ i ].next ){

 39         int next=edge[ i ].u;

 40         if( dfn[ next ]==-1 ){

 41             tarjan( next );

 42             low[ now ]=min( low[ now ],low[ next ]);

 43         }

 44         else if( vis[ next ]==1 ){

 45             low[ now ]=min( low[ now ],dfn[ next ] );

 46         }

 47     }

 48     if( low[ now ]==dfn[ now ] ){

 49         ans1++;

 50         while( 1 ){

 51             int tmp;

 52             tmp=q.top(),q.pop();

 53             vis[ tmp ]=0;

 54             belong[ tmp ]=ans1;

 55             if( tmp==now ) break;

 56         }

 57     }

 58 }

 59 

 60 int main(){

 61     while( scanf("%d%d",&n,&m)==2 ){

 62         for( int i=1;i<=n;i++ )

 63             scanf("%d",&cost[ i ]);

 64         init();

 65         int a,b;

 66         while( m-- ){

 67             scanf("%d%d",&a,&b);

 68             addedge( a,b );

 69         }

 70         while( !q.empty() ) q.pop();

 71         for( int i=1;i<=n;i++ ){

 72             if( dfn[ i ]==-1 ){

 73                 tarjan( i );

 74             }

 75         }

 76         memset( inde,0,sizeof( inde ));

 77         for( int i=0;i<cnt;i++ ){

 78             a=edge[ i ].v,b=edge[ i ].u;

 79             if( belong[ a ]!=belong[ b ] ){

 80                 inde[ belong[ b ] ]++;

 81             }

 82         }

 83         int ANS1,ANS2;

 84         ANS1=ANS2=0;

 85         int tmp_cnt[ maxn ];

 86         for( int i=1;i<=ans1;i++ ){

 87             if( inde[ i ]==0 )

 88                 ANS1++;//统计缩点之后,入度为0的点

 89             tmp_cnt[ i ]=inf;

 90         }

 91         for( int i=1;i<=n;i++ ){

 92             int tmp=belong[ i ];

 93             if( inde[ tmp ]==0 ){

 94                 tmp_cnt[ tmp ]=min( tmp_cnt[ tmp ],cost[ i ] );

 95             }

 96         }

 97         for( int i=1;i<=ans1;i++ ){

 98             if( tmp_cnt[ i ]!=inf )

 99                 ANS2+=tmp_cnt[ i ];

100         }

101         printf("%d %d\n",ANS1,ANS2);

102     }

103     return 0;

104 }

 

你可能感兴趣的:(tar)