[ACM Day3] A. A Journey to Greece

题目描述

给你一个包含 N N 个点的无向图,必须访问到其中指定的P个节点,与此同时,还有一张 T T 时间可以从当前点出发前往任意地点的车票,问是否能够在规定时间内访问完所有的指定点并回到出发点。如果可以不用车票输出“possible without taxi”,如果必须要车票输出“possible with taxi”,如果无法完成输出“impossible”。

数据范围

N<=2104P<=15M<=105

分析

P P 个点先跑一边dijstra,预处理P个点之间的距离,之后就是一个裸的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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值