[POJ3635]Full Tank? 题解

题目大意

给一张无向图,每个点有一个油价\(a_i\),表示每升油的单价。每条道路连接两个点,且有个权值\(w_i\),表示开过这条路所消耗的油量。现在有\(q\)个询问,每个询问给出一个油箱容量\(c\),一个起始点和一个终止点,要求出从起始点到终止点最少要消费多少钱。初始油箱为空。

分析

在状态中添加一维,\(d_{i,j}\) 表示当前在 \(i\) 号点,油量为 \(j\) 时的最小花费。

加油:\(d_{i,j} → d_{i,k}\) ,代价为 \(a_i × (k − j)\)

移动:\(d_{i,j} → d_{l,j-w_i}\),代价为 \(0\)

连边跑最短路。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std ;
const int MAXN = 1000 + 5 , MAXM = 10000 + 5 ;
struct Node {
    int next , to , w ;
} edge[ MAXM << 1 ] ;
int head[ MAXN ] , cnt ;
int n , m , c , q , s , t ;
int d[ MAXN ][ 305 ] ;
int a[ MAXN ] ;
bool vis[ MAXN ][ 305 ] ;
struct Node2 {
    int u , val , cc ;
    bool operator < ( const Node2& a ) const{
		return val>a.val;
	}
} ;
inline int read () {
    int tot = 0 , f = 1 ; char c = getchar () ;
    while ( c < '0' || c > '9' ) { if ( c == '-' ) f = -1 ; c = getchar () ; }
    while ( c >= '0' && c <= '9' ) { tot = tot * 10 + c - '0' ; c = getchar () ; }
    return tot * f ;
}
inline void add ( int x , int y , int z ) {
    edge[ ++ cnt ].next = head[ x ] ;
    edge[ cnt ].to = y ;
    edge[ cnt ].w = z ;
    head[ x ] = cnt ;
}
inline void spfa () {
    priority_queue < Node2 > q ;
    q.push ( ( Node2 ) { s , 0 , 0 } ) ;
    while ( q.size () ) {
        Node2 now = q.top () ; q.pop () ;
        int u = now.u , val = now.val , cc = now.cc ;
        vis[ u ][ cc ] = 1 ;
        if ( u == t ) {
            printf ( "%d\n" , val ) ;
            return ;
        }
        if ( cc + 1 <= c && ! vis[ u ][ cc + 1 ] && d[ u ][ cc ] + a[ u ] < d[ u ][ cc + 1 ] ) {
            d[ u ][ cc + 1 ] = d[ u ][ cc ] + a[ u ] ;
            q.push ( ( Node2 ) { u , d[ u ][ cc + 1 ] , cc + 1 } ) ;
		}
        for ( int i = head[ u ] ; i ; i = edge[ i ].next ) {
            int v = edge[ i ].to ;
            if ( cc >= edge[ i ].w && ! vis[ v ][ cc - edge[ i ].w ] && val < d[ v ][ cc - edge[ i ].w ] ) {
                d[ v ][ cc - edge[ i ].w ] = val ;
                q.push ( ( Node2 ) { v , d[ v ][ cc - edge[ i ].w ] , cc - edge[ i ].w } ) ;
            }
        }
    }
    printf ( "impossible\n" ) ;
}
signed main () {
    n = read () ; m = read () ;
    for ( int i = 0 ; i < n ; i ++ ) a[ i ] = read () ;
    for ( int i = 1 ; i <= m ; i ++ ) {
        int x = read () , y = read () , z = read () ;
        add ( x , y , z ) ; add ( y , x , z ) ;
    }
    q = read () ;
    while ( q -- ) {
        c = read () , s = read () , t = read () ;
        memset ( d , 0x3f , sizeof ( d ) ) ;
        memset ( vis , 0 , sizeof ( vis ) ) ;
        d[ s ][ 0 ] = 0 ;
        spfa () ;
    }
    return 0 ;
}

posted @ 2020-08-15 15:35  hulean  阅读(203)  评论(0编辑  收藏  举报