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 ;
}

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

转载于:https://www.cnblogs.com/misty1/archive/2013/01/28/2880494.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值