poj 2186 Popular Cows(第一道强连通分支题)

题意:有N头牛,选出最受欢迎的牛,其中有M对A B,表示牛A认为牛B比较受欢迎,问你有多少牛最受欢迎。

在学习强连通分支的Tarjan算法是,好多人提到这题时比较经典的强连通分支题,所以拿来练手了,熟悉一下Tarjan算法的实现过程。学习过程中还发现一篇讲解Tarjian算法很好的Blog, 

其中有图一步一步的讲解了Tarjan实现的过程,http://www.byvoid.com/blog/scc-tarjan/

代码:

View Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#define N 10004
#define M 50005
using namespace std ;

struct node
{
    int e ;
    int next ;
}p[M] ;

int node[N] ;
int dfn[N] , low[N] , belong[N] ;
int out[N] , cnt , f[N] ;
int index , res ;
int q[N] , top ;

void add( int x , int y )
{
    p[cnt].e = y ;
    p[cnt].next = node[x] ;
    node[x] = cnt++ ;
}

void init()
{
    cnt= 0 ;res =0 ;
    index = 1 ;top = 0 ;
    memset( node , -1 , sizeof( node ));
    memset( dfn , 0 , sizeof ( dfn ));
    memset( low , 0 ,sizeof ( low ));
    memset( belong , 0 , sizeof ( belong ));
    memset( out , 0 , sizeof ( out ));
    memset( f , 0 , sizeof ( f ));
    memset( q , 0 , sizeof ( q ));
}

int min ( int x , int y )
{
    return x < y ? x : y ;
}

void dfs( int i )
{
    int j ;
    dfn[i] = low[i] = index++ ;
    q[top++] = i ;
    f[i] = 1 ;
    for ( j = node[i] ; j != -1 ; j = p[j].next )
    {
        int x = p[j].e ;
        if ( !dfn[x] )
        {
            dfs( x );
            low[i] = min( low[i] , low[x] );
        }
        else if( f[x] )
        low[i] = min( dfn[x] , low[i] );
    }
    if ( dfn[i] == low[i] )
    {
        int y ;
        res++ ;
        do
        {
            y = q[--top] ;
            f[y] = 0 ;
            belong[y] = res;
        }while ( y != i );
    }
}

void find( int n )
{
    int i , j ;
    for ( i = 1 ; i <= n ; i++ )
    {
        for( j = node[i] ; j != -1 ; j = p[j].next )
        if ( belong[i] != belong[p[j].e] )
        out[belong[i]]++ ;
    }
    int num , mark ;
    num = 0 ;
    for ( i = 1 ; i <= res ; i++ )
    if ( !out[i] )
    {
        num++;
        mark = i ;
    }
    if ( num == 1 )
    {
        int sum = 0 ;
        for ( i = 1 ; i <= n ; i++ )
        if ( belong[i] == mark )
        sum++ ;
        cout<<sum<<endl;
    }
    else
    cout<<"0\n";
}

int main()
{
    int n , m , i , a , b  ;

    while(cin>>n>>m )
    {
        init();
        for ( i = 1 ; i <= m ; i++ )
        {
            cin>>a>>b ;
            add( a , b );
        }
        for ( i = 1 ; i <= n ; i++ )
        if ( !dfn[i] )
        dfs( i );
        find( n );
    }
    return 0 ;
}

接下来,继续学习强连通的其他算法。

原文地址:https://www.cnblogs.com/misty1/p/2613576.html