zoukankan      html  css  js  c++  java
  • ural Shortest Subchain(最短路)

    题意比较好理解,但是题目给出的要求却比较麻烦,给出的有向边是有顺序的,后面的边不能用在它前面出现的边,因为题目要求找出的最短路必须是按照给出的顺序,麻烦就麻烦在这,否则一遍bfs就找出最短路了,看到discuss里有人说可以用O(n)过,但是就是没想出来,最后,不得不查了解题报告,看到有人是将点的位置进行连线,相邻位置之间设为1,如果临近的相同元素之间设为0 ,这样从0~n-1找一天最短路就可以了。

    Hint:n是大于100000,开到10^6差不多,因为这挂在了15组数据上一次了。

    代码:

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <math.h>
    #include <map>
    #include <queue>
    #include <vector>
    #include <stack>
    #define  N 1000004
    #define  INF 1000000000
    using namespace std ;
    
    struct node
    {
        int to ;
        int val ;
        int next ;
    }p[N] ;
    int head[N] , h[N] , d[N] ;
    bool vist[N] ;
    int dis[N] , n , m , pre[N] ;
    queue<int>q ;
    
    void init()
    {
        memset( head , -1 , sizeof ( head )) ;
        memset( h , -1 , sizeof ( h )) ;
        memset( vist , false , sizeof ( vist )) ;
        for ( int i = 0 ; i <= n ; i++ )
        {
            pre[i] = -1 ;
            dis[i] = INF ;
        }
        while( !q.empty()) q.pop();
        m = 0 ;
    }
    
    void add( int x , int y , int z )
    {
        p[m].to = y ;
        p[m].val = z ;
        p[m].next = head[x] ;
        head[x] = m++ ;
    }
    
    void Spfa( int s )
    {
        dis[s] = 0 ;
        vist[s] = true ;
        q.push( s ) ;
        int u , v , i ;
    
        while ( !q.empty())
        {
            u = q.front() ;
            q.pop();
            vist[u] = false ;
    
            for ( i = head[u] ; i != -1 ; i = p[i].next )
            {
                v = p[i].to ;
                if ( dis[v] > dis[u] + p[i].val )
                {
                    dis[v] = dis[u] + p[i].val ;
                    pre[v] = u ;
                    if( !vist[v] )
                    {
                        vist[v] = true ;
                        q.push( v ) ;
                    }
                }
            }
        }
    }
    
    void output( int x )
    {
        if ( x == -1 )
        return ;
        output( pre[x] ) ;
        if ( d[pre[x]] == d[x] )
        return ;
        if( pre[x] == -1 )
        printf ( "%d" , d[x] ) ;
        else
        printf ( " %d" , d[x] ) ;
    }
    
    int main()
    {
        int i , k ;
    
        while ( scanf ( "%d" , &n ) != EOF )
        {
            init() ;
            for ( i = 0 ; i < n - 1 ; i++ )
            add( i , i + 1 , 1 ) ;
    
            for ( i = 0 ; i < n ; i++ )
            {
                scanf ( "%d" , &d[i] ) ;
                k = d[i] ;
                if ( h[k] != -1 )
                {
                    add( h[k] , i , 0 );
                }
                h[k] = i ;
            }
    
            Spfa( 0 ) ;
            output( n - 1 ) ;
            printf( "\n" ) ;
        }
        return 0 ;
    }

    学了这么久的最短路,用起来还是不过灵活啊。。。。。

  • 相关阅读:
    MongoDB下配置用户权限
    (CF)Codeforces445A DZY Loves Chessboard(纯实现题)
    C语言概述
    C#中值类型和引用类型的差别浅记
    Qt5官方demo解析集30——Extending QML
    汉澳sinox通过ndis执行windows驱动程序
    linux设备驱动归纳总结(三):4.ioctl的实现【转】
    linux设备驱动归纳总结(三):3.设备驱动面向对象思想和lseek的实现【转】
    linux设备驱动归纳总结(三):2.字符型设备的操作open、close、read、write【转】
    linux设备驱动归纳总结(三):1.字符型设备之设备申请【转】
  • 原文地址:https://www.cnblogs.com/misty1/p/2880494.html
Copyright © 2011-2022 走看看