zoukankan      html  css  js  c++  java
  • HDU Intelligence System(tarjan+缩点)

    http://acm.hdu.edu.cn/showproblem.php?pid=3072

    最近为了CF上的一道题,又把强连通分支的tarjan算法看了一遍,为了加深印象,就做了HDU上的这题。。。。

    题意:有一个情报系统,要从0开始传播一个情报,如果两个人可以互达那么两人之间的传播费用为0 ,否则两人之间的传播费用为ci,求要情报传达到每个人的最小费用。

    思路:既然一个强连通分支内的传播费用为0,求图中有几个强连通分支,缩点后求各点之间的最小费用。

    代码:

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <stack>
    #define  N 100005
    #define  M 50005
    using namespace std ;
    
    const int INF = ( 1 << 30 );
    
    struct node
    {
        int e , len ;
        int next ;
    }p[N] ;
    
    int head[M] , n , m , num , cnt , id ;
    bool used[M] , vist[M] ;//used[i]表示点i是否遍历过,vist[i]表示点i是否在栈里;
    int dis[M] , dfn[M] , low[M] , belong[M] ;
    stack<int>q ;
    
    //初始化
    void init()
    {
        num = cnt = id = 0 ;
        for ( int i = 0 ; i <= n ; i++ )
        {
            dfn[i] = low[i] = 0 ;
            used[i] = vist[i] = false ;
            dis[i] = INF ;
            head[i] = -1 ;
        }
        while ( !q.empty()) q.top();
    }
    
    void add ( int x , int y , int z )
    {
        p[num].e = y ;
        p[num].len = z ;
        p[num].next = head[x];
        head[x] = num++ ;
    }
    
    void tarjan( int x )
    {
        int i , v ;
        dfn[x] = low[x] = ++id ;
        used[x] = vist[x] = true ;
        q.push( x ) ;
        for ( i = head[x] ; i != -1 ; i = p[i].next )
        {
            v = p[i].e ;
            if( !used[v] )
            {
                tarjan( v ) ;
                low[x] = min( low[x] , low[v] );
            }
            else if( vist[v] )
            {
                low[x] = min( low[x] , dfn[v] );
            }
        }
    
        if ( dfn[x] == low[x] )
        {
            cnt++ ;
            do
            {
                v = q.top();
                q.pop();
                belong[v] = cnt ;
                vist[v] = false ;
            }while( v != x ) ;
        }
    }
    
    int main()
    {
        int i , j , x , y , z ;
    
        while ( scanf ( "%d%d" , &n , &m ) != EOF )
        {
            init();
            for ( i = 1 ; i <= m ; i++ )
            {
                scanf ( "%d%d%d" , &x , &y , &z );
                //x++ ; y++ ;
                add ( ++x , ++y , z ) ;
            }
    
            for ( i = 1 ; i <= n ; i++ )
            if ( !dfn[i] )
            tarjan( i ) ;
    
            for ( i = 1 ; i <= n ; i++ )
            {
                for ( j = head[i] ; j != -1 ; j = p[j].next )
                {
                    z = p[j].e ;
                    x = belong[i]; y = belong[z] ;
                    if ( x != y )
                    dis[y] = min( dis[y] , p[j].len ) ;
                }
            }
    
            int sum = 0 ;
            for ( i = 1 ; i <= n ; i++ )
            if ( dis[i] < INF )
            sum += dis[i] ;
    
            printf ( "%d\n" , sum ) ;
        }
        return 0 ;
    }
  • 相关阅读:
    Leetcode 283. Move Zeroes
    算法总结
    随机森林
    BRICH
    DBSCAN算法
    k-means算法的优缺点以及改进
    soket编程
    手电筒过河
    字符串反转
    URAL 1356. Something Easier(哥德巴赫猜想)
  • 原文地址:https://www.cnblogs.com/misty1/p/2752327.html
Copyright © 2011-2022 走看看