题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1003
刚开始看题目有点晕,盯了vfleaking大神的题解(Orz)半天之后猛然觉悟,然后猛敲一顿SPFA+DP,1次水过。。。
代码:
fcfaaf51f3deb48f4e935aa9f21f3a292cf578cb.jpg.png
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <deque>
using namespace std ;
#define MAXN 110
#define MAXM 30
#define inf ( 1 << 20 )
int n , m ;
struct graph {
struct edge {
edge *next ;
int t , d ;
} *head[ MAXM ] ;
graph ( ) {
memset( head , 0 , sizeof( head ) ) ;
}
void Add( int s ,int t ,int d ) {
edge *p = new( edge ) ;
p -> t = t , p -> d = d , p -> next = head[ s ] ;
head[ s ] = p ;
}
void AddEdge( int s , int t , int d ) {
Add( s , t , d ) , Add( t , s , d ) ;
}
bool flag[ MAXM ] , f[ MAXM ] , va[ MAXM ][ MAXN ] ;
int dist[ MAXM ] ;
deque< int > Q ;
int spfa( ) {
for ( int i = 0 ; i ++ < m ; ) f[ i ] = false , dist[ i ] = inf ;
long long sum = 0 ; Q.clear( ) ;
dist[ 1 ] = 0 , f[ 1 ] = true , Q.push_back( 1 ) ;
while ( ! Q.empty( ) ) {
while ( dist[ Q.front( ) ] > sum / Q.size( ) + 1 ) Q.push_back( Q.front( ) ) , Q.pop_front( ) ;
int v = Q.front( ) ; Q.pop_front( ) ;
f[ v ] = false , sum -= dist[ v ] ;
for ( edge *p = head[ v ] ; p ; p = p -> next ) if ( flag[ p -> t ] && dist[ p -> t ] > dist[ v ] + p -> d ) {
if ( f[ p -> t ] ) sum -= dist[ p -> t ] ;
sum += ( dist[ p -> t ] = dist[ v ] + p -> d ) ;
if ( ! f[ p -> t ] ) {
f[ p -> t ] = true ;
if ( Q.empty( ) ) Q.push_back( p -> t ) ; else if ( dist[ p -> t ] < dist[ Q.front( ) ] ) Q.push_front( p -> t ) ; else Q.push_back( p -> t ) ;
}
}
}
return dist[ m ] ;
}
int cost( int l , int r ) {
memset( flag , true , sizeof( flag ) ) ;
for ( int i = 0 ; i ++ < m ; ) for ( int j = l ; j <= r ; j ++ ) if ( ! va[ i ][ j ] ) {
flag[ i ] = false ; break ;
}
return spfa( ) ;
}
} g ;
int dp[ MAXN ] , k , e , d ;
int main( ) {
memset( g.va , true , sizeof( g.va ) ) ;
scanf( "%d%d%d%d" , &n , &m , &k , &e ) ;
while ( e -- ) {
int s , t , v ;
scanf( "%d%d%d" , &s , &t , &v ) ;
g.AddEdge( s , t , v ) ;
}
scanf( "%d" , &d ) ;
while ( d -- ) {
int p , a , b;
scanf( "%d%d%d" , &p , &a , &b ) ;
for ( int i = a ; i <= b ; i ++ ) g.va[ p ][ i ] = false ;
}
for ( int i = 0 ; i ++ < n ; ) {
dp[ i ] = g.cost( 1 , i ) * i ;
for ( int j = 0 ; j ++ < i - 1 ; ) dp[ i ] = min( dp[ i ] , dp[ j ] + g.cost( j + 1 , i )*( i - j ) + k ) ;
}
printf( "%d\n" , dp[ n ] ) ;
return 0 ;
}
网友评论