zoukankan      html  css  js  c++  java
  • 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 ;
    }

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

  • 相关阅读:
    关于C++名字空间
    选择组合OR继承?
    编译器为C++ 空类自动生成的成员函数
    函数返回值为引用类型
    关于数据库存储过程分页DatagridView BindingNavigator 控件的详细实现
    ADO.NET 安全编码指南 来自MSDN
    ADO.NET中调用存储过程
    视图
    高效使用连接的模式
    GROUP BY, HAVING, COMPUTE, ORDER BY 语句
  • 原文地址:https://www.cnblogs.com/misty1/p/2613576.html
Copyright © 2011-2022 走看看