题目描述
给你一个包含 N N 个点的无向图,必须访问到其中指定的个节点,与此同时,还有一张 T T 时间可以从当前点出发前往任意地点的车票,问是否能够在规定时间内访问完所有的指定点并回到出发点。如果可以不用车票输出“possible without taxi”,如果必须要车票输出“possible with taxi”,如果无法完成输出“impossible”。
数据范围
分析
对 P P 个点先跑一边dijstra,预处理个点之间的距离,之后就是一个裸的TSP问题,注意需要建一个虚点来计算需要taxi的情况。
#include <bits/stdc++.h>
#define rep( i , l , r ) for( int i = (l) ; i <= (r) ; ++i )
#define per( i , r , l ) for( int i = (r) ; i >= (l) ; --i )
#define erep( i , u ) for( int i = head[(u)] ; ~i ; i = e[i].nxt )
using namespace std;
int _read(){
char ch = getchar();
int x = 0 , f = 1 ;
while( !isdigit( ch ) )
if( ch == '-' ) f = -1 , ch = getchar();
else ch = getchar();
while( isdigit( ch ) )
x = (ch - '0') + x * 10 , ch = getchar();
return x * f;
}
const int maxn = 2e4 + 10 , maxm = 2e5 + 100;
struct edge{
int v , w , nxt;
} e[2 * maxm];
int head[maxn] , _t = 0;
inline void addedge( int u , int v , int w ){
e[_t].v = v , e[_t].w = w , e[_t].nxt = head[u] , head[u] = _t++;
}
struct node{
int x , d;
node( int x , int d ) : x(x) , d(d) {}
bool operator <(const node &b) const{
return d > b.d;
}
};
priority_queue<node> q;
int d[20][maxn];
void dijstra( int s , int t ){
memset( d[t] , 0x3f , sizeof d[t] );
d[t][s] = 0 ; q.push( node( s , 0 ) );
while( !q.empty() ){
int u = q.top().x , dist = q.top().d; q.pop();
if( d[t][u] != dist ) continue;
erep( i , u ){
int v = e[i].v;
if( d[t][v] > d[t][u] + e[i].w ){
d[t][v] = d[t][u] + e[i].w;
q.push( node( v , d[t][v] ) );
}
}
}
}
int dis[20][20] , a[20];
int f[1 << 18][18];
const int INF = 0x3f3f3f3f;
inline int _min( int a , int b ){ return a < b ? a : b ; }
int main(){
int N , P , M , G , T;
scanf("%d %d %d %d %d" , &N , &P , &M , &G , &T );
memset( head , 0xff , sizeof head );
int sum = 0 , t;
bool flg = 1;
rep( i , 0 , P - 1 ){
scanf("%d %d" , &a[i] , &t);
if( 0 == a[i] ) flg = 0;
sum += t;
}
if( flg ) a[P++] = 0;
sort( a , a + P );
int u , v , w;
rep( i , 0 , M - 1 ){
scanf("%d %d %d" , &u , &v , &w);
addedge( u , v , w );
addedge( v , u , w );
}
rep( i , 0 , P - 1 ) dijstra( a[i] , i );
rep( i , 0 , P - 1 )
rep( j , 0 , P - 1 )
dis[i][j] = d[i][a[j]];
++P;
memset( f , 0x3f , sizeof f );
f[0][0] = 0;
for(int s = 0 ; s < (1 << P) ; ++s )
rep( i , 0 , P - 2 ){
if( f[s][i] == INF ) continue;
rep( j , 0 , P - 2 ){
if( s & (1 << j) ) continue;
if( dis[i][j] != INF ) f[s | (1 << j)][j] = _min( f[s | (1 << j)][j] , f[s][i] + dis[i][j]);
}
if( !(s&(1<<(P-1))) ){
rep( j , 0 , P - 2 ){
if( s & (1 << j) ) continue;
int nxt = s | (1 << j);
nxt |= (1 << (P - 1));
f[nxt][j] = _min( f[nxt][j] , f[s][i] + T );
}
}
}
if( f[(1 << (P - 1)) - 1][0] + sum <= G ) puts("possible without taxi");
else if( f[(1 << P) - 1][0] + sum <= G ) puts("possible with taxi");
else puts("impossible");
return 0;
}