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