• poj 3114 Countries in War(tarjan + spfa)


    http://poj.org/problem?id=3114

    题意:给出N个城市和M条路,每封信可以从城市A到城市B花费时间ci,但路是单向的,如果两个城市可以互达,则这两个城市属于同一个国家,而一封信在同一个国家间传递不花费时间,然后给出K组查询,问从X到Y所花的最小时间。

    解题过程:这题和poj上的3592一样,先求出图中的强连通分支,缩点后去最短路,用的spfa求最短路,discuss里有人说floyd会超时,所以直接用了spfa,但是开始的时候数组开小了,找了好久才找出来。

    代码:

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #define  N 505
    #define  M 250006
    using namespace std ;
    
    const int INF = ( 1 << 30 ) ;
    
    struct node
    {
        int e , val ;
        int next ;
    }p[M] , q[M] ;
    
    int headp[N] , headq[N] , dfn[N] , low[N] , dis[N] , belong[N] ;
    bool vist[N] , used[N] ;
    int n , m , cnt , id , nump , numq ;
    queue<int>qx ;
    stack<int>st ;
    
    void addp ( int x , int y , int z )
    {
        p[nump].e = y ;
        p[nump].val = z ;
        p[nump].next = headp[x] ;
        headp[x] = nump++ ;
    }
    
    void addq ( int x , int y , int z )
    {
        q[numq].e = y ;
        q[numq].val = z ;
        q[numq].next = headq[x] ;
        headq[x] = numq++ ;
    }
    
    void init()
    {
        nump = numq = 0 ;
        cnt = id = 0 ;
        memset( headp , -1 , sizeof ( headp )) ;
        memset( headq , -1 , sizeof ( headq )) ;
        memset( dfn , 0 , sizeof ( dfn )) ;
        memset( low , 0 , sizeof ( low )) ;
        memset( belong , 0 , sizeof ( belong )) ;
        for (int i = 1 ; i <= n ; i++ )
        {
            //dis[i] = INF ;
            vist[i] = used[i] = false ;
        }
        while ( !st.empty()) st.pop();
    }
    
    void tarjan( int x )
    {
        int u , v ;
        dfn[x] = low[x] = ++id ;
        used[x] = vist[x] = true ;
        st.push( x ) ;
    
        for ( int i = headp[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
            {
                u = st.top();
                st.pop();
                belong[u] = cnt ;
                vist[u] = false ;
            }while ( u != x ) ;
        }
    }
    
    void Spfa( int s )
    {
        int u , v ;
        while ( !qx.empty()) qx.pop();
        for ( u = 0 ; u <= n ; u++ )
        {
            dis[u] = INF ;
            vist[u] = false ;
        }
        dis[s] = 0 ;
        vist[s] = true ;
        qx.push( s ) ;
    
        while ( !qx.empty())
        {
            u = qx.front();
            qx.pop();
            vist[u] = false ;
    
            for ( int i = headq[u] ; i != -1 ; i = q[i].next )
            {
                v = q[i].e ;
                if ( dis[v] > dis[u] + q[i].val )
                {
                    dis[v] = dis[u] + q[i].val ;
                    if ( !vist[v] )
                    {
                        vist[v] = true ;
                        qx.push( v ) ;
                    }
                }
            }
        }
    }
    
    int main()
    {
        int i , j , x , y , z , k ;
    
        //freopen( "input.txt" , "r" , stdin ) ;
        while ( scanf ( "%d%d" , &n , &m ) , n + m )
        {
            //初始化
            init();
            for ( i = 1 ; i <= m ; i++ )
            {
                scanf ( "%d%d%d" , &x , &y , &z ) ;
                addp ( x , y , z ) ;
            }
            
            //求强连通分支
            for ( i = 1 ; i <= n ; i++ )
            if ( !dfn[i] )
            tarjan( i );
            
            //缩点后建图
            for ( i = 1 ; i <= n ; i++ )
            {
                for ( j = headp[i] ; j != -1 ; j = p[j].next )
                {
                    x = p[j].e ;
                    if ( belong[i] != belong[x] )
                    {
                        addq ( belong[i] , belong[x] , p[j].val ) ;
                    }
                }
            }
            /*for ( i = 1 ; i <= n ; i++ )
            {
                cout<<i<<":"<<belong[i]<<endl ;
            }*/
            //cout<<numq<<endl;
            
            //查询
            scanf ( "%d" , &k ) ;
            while ( k-- )
            {
                scanf ( "%d%d" , &x , &y ) ;
                if ( belong[x] == belong[y] && belong[x] != 0 )
                {
                    printf ( "0\n" );
                    continue ;
                }
                x = belong[x] ;
                y = belong[y] ;
                Spfa( x ) ;
                if ( dis[y] == dis[0] )
                {
                    printf ( "Nao e possivel entregar a carta\n" );
                }
                else
                {
                    printf ( "%d\n" , dis[y] ) ;
                }
            }
            printf ( "\n" );
        }
        return 0 ;
    }

     

  • 相关阅读:
    [Tip: VS debugging]F5 VS Ctrl +F5
    C#: boxing and unboxing
    [Tip: check overflow/underflow C#]
    C# floating Point types
    UVa 103 Stacking Box(记忆化搜索)
    POJ 3321 apple tree(树形数组)
    UVa 116 Unidirectional TSP(简单旅行商DP)
    UVa 562 Dividing coins(简单DP)
    UVa 10003 Cutting Sticks(区间DP)
    UVa 348 Optimal Array Multiplication Sequence(链式DP/区间DP)
  • 原文地址:https://www.cnblogs.com/misty1/p/2754115.html
Copyright © 2020-2023  润新知