BZOJ-3040: 最短路(road)(配对堆优化Dijkst

作者: AmadeusChan | 来源:发表于2018-10-17 12:30 被阅读2次

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3040

    用二叉堆优化Dijkstra算法的话是O( ( n + m ) log n ),明显会TLE,所以要用斐波那契堆或者配对堆来优化,这两种堆插入的复杂度均为O(1),因此可以Dijkstra优化到O( n log n + m ),A过此题。。。(斐波那契堆代码实在是太那啥了不敢写,应该手残了一下配对堆,没想到一次就水过了。一篇关于配对堆不错的介绍:)

    代码(配对堆,事实上跟二叉堆一样好写,代码也很短):

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
     
    using namespace std ;
     
    #define ll long long 
    #define MAXN 1000001
     
    struct edge {
        edge *next ;
        int t , d ;
    } *head[ MAXN ] ;
     
    void AddEdge( int s , int t , int d ) {
        edge *p = new( edge ) ;
        p -> t = t , p -> d = d , p -> next = head[ s ] ;
        head[ s ] = p ;
    }
     
    ll dist[ MAXN ] ;
    bool f[ MAXN ] ;
    const ll inf = ( ll )( 0x7fffffff ) * ( ll )( 0x7fffffff ) ;
    int n , m ;
    ll T , rxa , rxc , rya , ryc , rp ;
     
    struct node {
        int left , right , child ;
        node(  ) {
            left = right = child ;
        }
    } h[ MAXN ] ;
     
    int roof = 0 ;
     
    int Join( int v , int u ) {
        if ( dist[ v ] < dist[ u ] ) swap( v , u ) ;
        h[ v ].left = u , h[ v ].right = h[ u ].child , h[ h[ u ].child ].left = v ; 
        h[ u ].child = v ; 
        return u ;
    }
     
    void Push( int v ) {
        if ( ! roof ) roof = v ; else roof = Join( roof , v ) ;
    }
     
    int Top(  ) {
        return roof ;
    }
     
    void Update( int v ) {
        if ( v != roof ) {
            if ( h[ h[ v ].left ].child == v ) {
                h[ h[ v ].left ].child = h[ v ].right ;
            } else {
                h[ h[ v ].left ].right = h[ v ].right ;
            }
            if ( h[ v ].right ) h[ h[ v ].right ].left = h[ v ].left ;
            h[ v ].left = h[ v ].right = 0 ;
            roof = Join( roof , v ) ;
        }
    }
     
    int sta[ MAXN ] , top ;
     
    void Pop(  ) {
        if ( ! h[ roof ].child ) roof = 0 ; else {
            top = 0 ;
            int t = h[ roof ].child ;
            while ( t ) {
                if ( h[ t ].right ) {
                    int k = h[ h[ t ].right ].right ;
                    int v = h[ t ].right ;
                    h[ t ].left = h[ t ].right = h[ v ].left = h[ v ].right = 0 ;
                    sta[ ++ top ] = Join( v , t ) ;
                    t = k ;
                } else {
                    sta[ ++ top ] = t ;
                    h[ t ].left = h[ t ].right = 0 ;
                    break ;
                }
            }
            roof = sta[ top ] ;
            for ( int i = top - 1 ; i ; -- i ) roof = Join( roof , sta[ i ] ) ;
        }
    }
     
    void Dijstra(  ) {
        memset( f , false , sizeof( f ) ) ;
        for ( int i = 0 ; i ++ < n ; ) dist[ i ] = inf ;
        dist[ 1 ] = 0 , Push( 1 ) , f[ 1 ] = true ;
        for ( int i = 0 ; i ++ < n - 1 ; ) {
            int v = Top(  ) ; Pop(  ) , f[ v ] = false ;
            if ( v == n ) break ;
            for ( edge *p = head[ v ] ; p ; p = p -> next ) if ( dist[ p -> t ] > dist[ v ] + ( ll )( p -> d ) ) {
                dist[ p -> t ] = dist[ v ] + ( ll )( p -> d ) ;
                if ( ! f[ p -> t ] ) Push( p -> t ) , f[ p -> t ] = true ; else Update( p -> t ) ;
            }
        }
    }
     
    int main(  ) {
        scanf( "%d%d" , &n , &m ) ;
        scanf( "%lld%lld%lld%lld%lld%lld" , &T , &rxa , &rxc , &rya , &ryc , &rp ) ;
        memset( head , 0 , sizeof( head ) ) ;
        ll x = 0 , y = 0 , z = 0 ;
        for ( int i = 0 ; i ++ < T ; ) {
            x = ( x * rxa + rxc ) % rp ;
            y = ( y * rya + ryc ) % rp ;
            ll a = x % n + 1 , b = y % n + 1 ;
            if ( a > b ) swap( a , b ) ;
            ll d = ( ll )( 100000000 ) - 100 * a ;
            AddEdge( a , b , d ) ;
        }
        for ( int i = 0 ; i ++ < m - T ; ) {
            int s , t ; ll d ; scanf( "%d%d%lld" , &s , &t , &d ) ;
            AddEdge( s , t , d ) ;
        }
        Dijstra(  ) ;
        printf( "%lld\n" , dist[ n ] ) ;
        return 0 ;
    }
    

    相关文章

      网友评论

        本文标题:BZOJ-3040: 最短路(road)(配对堆优化Dijkst

        本文链接:https://www.haomeiwen.com/subject/klnlzftx.html