旅游景点 Tourist Attractions 做题感受
这个题调了今天(早预备+体育课+第五节+中午20分钟+晚新闻+晚三),终于搞出来了,写个题解(根本不是题解,就是一划水帖子)纪念一下
这道题思路还是很好想的,我一开始就想到了对范围较小的\(k\)下手,然后很愉快的推出方程,然后开始了各种错误
错误1:一开始把\(define\ int\ long\ long\),空间直接翻倍直接炸成\(0\),以后要计算一下是否爆\(int\)再操作,同时学会了空间计算方法
int 4个字节 , long long 8个字节 , bool 1个字节 , 一个 bit \(1/4\)个字节 , \(1024 * 1024\)字节等于\(1MB\)
错误2:先枚举顶点再枚举状态,历史总是惊人的相似,我没次都要犯这个沙雕错误,导致调试半天(就做了3个枚举两层三次都错了)
错误3:由于学校oj上空间严格给的\(357MB\),所以不能把起点和终点也进行状态压缩,需要额外i跑两边\(dj\)求出每个点到起点和终点的距离
错误4:由于空间比较卡的慌,所以我们需要利用一下\(0\)这个空间,可以直接让空间减小一倍
错误5:\(cmath里面的log\)函数并不稳定,最好自己手写\(O(n)\)预处理
lg [0] = -1 ;
for( R i = 1 ; i <= ( 1 << s ) ; i ++ ) lg [i] = lg [i / 2] + 1 ;
错误6:由于没有计算起点和终点,所以要特判一下\(k==0\)的情况,直接$dj\ 1 - n $的最短路
错误7:经典错误,\(dj\)里面初始化不能初始化成0x7f,要初始化成0x3f.
没啥了吧
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <iostream>
#include <queue>
#include <cmath>
#define R register int
//#define int long long
#define PI pair< int , int >
#define mp make_pair
using namespace std ;
const int N = 2e4 + 10 ;
const int M = 4e5 + 10 ;
typedef long long L ;
typedef double D ;
inline int read(){
int w = 0 ; bool fg = 0 ; char ch = getchar() ;
while( ch > '9' || ch < '0' ) fg |= ( ch == '-' ) , ch = getchar() ;
while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch - '0' ) , ch = getchar() ;
return fg ? -w : w ;
}
int n , m , ks , qs , s [N] , dis [N] , fg [N] , f [21][1 << 21] ; // f [i][j] 表示j状态且目前出去i点的MIN Ans : f [ks(n)][(i << ks )- 1]
int x , y , z , head [N] , cnt , ds [25][25] , lg [1 << 22] ;
struct E{ int fr , to , w , next ; } a [M] ;
priority_queue< PI , vector< PI > , greater< PI > > q ;
inline void debug( int x ){ cout << bitset<10> ( x ) << endl ; }
inline void add( int f , int t , int w ){
a [++ cnt].fr = f ; a [cnt].to = t ;
a [cnt].w = w ; a [cnt].next = head [f] , head [f] = cnt ;
}
inline void dj( int x ){
memset( dis , 0x3f , sizeof( dis ) ) , memset( fg , 0 , sizeof( fg ) ) ;
dis [x] = 0 ; q.push( mp ( 0 , x ) ) ;
while( !q.empty() ){
int x = q.top().second ; q.pop() ;
if( fg [x] ) continue ; fg [x] = 1 ;
for( R i = head [x] ; ~i ; i = a [i].next ){
int y = a [i].to ;
if( dis [y] > dis [x] + a [i].w )
dis [y] = dis [x] + a [i].w , q.push( mp( dis [y] , y ) ) ;
}
} x -- ;
// printf( "THIS IS%d\n" , x ) ;
// for( R i = 0 ; i < n ; i ++ ) printf( "%d %d\n" , i , dis [i] ) ;
for( R i = 1 ; i <= ks ; i ++ ) ds [x][i - 1] = dis [i] ; ds [x][ks] = dis [n - 1] ;
// for( R i = 0 ; i <= ks ; i ++ ) printf( "%d\n" , ds [x][i] ) ; //printf( "%d\n" , ds [x][ks + 1] ) ;
}
inline void dsj(){
memset( dis , 0x3f , sizeof( dis ) ) , memset( fg , 0 , sizeof( fg ) ) ;
dis [0] = 0 ; q.push( mp ( 0 , 0 ) ) ;
while( !q.empty() ){
int x = q.top().second ; q.pop() ;
if( fg [x] ) continue ; fg [x] = 1 ;
for( R i = head [x] ; ~i ; i = a [i].next ){
int y = a [i].to ;
if( dis [y] > dis [x] + a [i].w )
dis [y] = dis [x] + a [i].w , q.push( mp( dis [y] , y ) ) ;
}
}
for( R i = 1 ; i <= ks ; i ++ ) ds [24][i - 1] = dis [i] ; ds [24][ks] = dis [n - 1] ;
}
inline void ddj(){
memset( dis , 0x3f , sizeof( dis ) ) , memset( fg , 0 , sizeof( fg ) ) ;
dis [0] = 0 ; q.push( mp ( 0 , 0 ) ) ;
while( !q.empty() ){
int x = q.top().second ; q.pop() ;
if( fg [x] ) continue ; fg [x] = 1 ;
for( R i = head [x] ; ~i ; i = a [i].next ){
int y = a [i].to ;
if( dis [y] > dis [x] + a [i].w )
dis [y] = dis [x] + a [i].w , q.push( mp( dis [y] , y ) ) ;
}
} printf( "%d\n" , dis [n - 1] ) ; exit( 0 ) ;
}
inline int lb( int x ){ return x & -x ; }
void sc(){
n = read() , m = read() , ks = read() ; memset( head , -1 , sizeof( head ) ) ;
lg [0] = -1 ; for( R i = 1 ; i < ( 1 << 22 ) ; i ++ ) lg [i] = lg [i / 2] + 1 ;
// for( R i = 0 ; i <= n ; i ++ ) printf( "%lld\n" , lg [i] ) ;
for( R i = 1 ; i <= m ; i ++ ) x = read() , y = read() , z = read() , x -- , y -- , add( x , y , z ) , add( y , x , z ) ;
if( !ks ) ddj() ; qs = read() ;
for( R i = 1 ; i <= qs ; i ++ ){
x = read() , y = read() ; x -=2 , y -= 2 ;
s [x] |= ( 1 << y ) ; //debug( s [x] ) ;
} for( R i = 1 ; i <= ks ; i ++ ) dj( i ) ;
dsj() ;
}
void works(){
memset( f , 0x3f , sizeof( f ) ) ;
for( R i = 0 ; i <= ks ; i ++ ) f [i][1 << i] = ds [24][i] ;
for( R j = 1 ; j < 1 << ks ; j ++ ){
for( R i = 0 ; i <= ks ; i ++ ){
for( R k = j ; k ; k -= lb( k ) ){
int t = lb( k ) , fs = j ^ t ;
// t = (int)( (D)(log(t))/(D) (log(2)) ) ; //t ++ ;
t = lg [t] / lg [2] ;
if( fs & s [t] ) continue ;
if( ! (( fs >> i ) & 1 ) ) continue ;
// if( ! (() >> ( )) )
f [t][j] = min( f [t][j] , f [i][fs] + ds [i][t] ) ;
// printf( "%d " , i ) , debug( fs ) ;
// printf( "%d " , t ) , debug( j ) ; printf( "LONG%d " , ds [i][t] ) ;
// printf( "%d %d\n" , f [t][j] , f [i][fs] ) , puts( "" ) ;
}
}
} int ans = 0x3f3f3f3f ;
for( R i = 0 ; i <= ks ; i ++ ) ans = min( ans , f [i][(1 << ks) - 1] + ds [i][ks] ) ;
printf( "%d\n" , ans ) ;
}
signed main(){
// freopen( "1.out" , "w" , stdout ) ;
// printf( "LOG%d\n" , (int)( (D)(log(9))/(D) (log(2)) )) ;
sc() ;
works() ;
return 0 ;
}
$The \ light \ has \ betrayed \ me$

浙公网安备 33010602011771号