一、题目大意
有N个城市,一个人要从城市1前往城市N。路是单向的,且经过一条路需要花费时间t
以及过路费c
。现在这个人有K
元钱,问最短需要多少时间到城市N,若无法到达,输出-1
二、解题思路
这是一个改版的最短路问题。我们存储状态时存储(city, time, cost)
的三元组。我们按照以下策略剪枝:
- 当
cost>K
, 减掉 - 令
dist[i][cost]
: 从城市1到城市i花费cost时所花的最少时间。所以当dist[city][cost] <= time
,减掉。
之所以使用dist[i][cost]
而不使用dist[i][time]
作为剪枝条件,是因为,cost
有上界K
,而time
没有。
三、代码
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
const int MAXN = 105;
const int inf = 1 << 30;
struct Node
{
int city, t, c;
bool operator < (const Node &A)const{
if(t == A.t)
return c >= A.c;
return t > A.t;
}
}tmp;
priority_queue<Node> Q;
vector<Node> G[MAXN];
int d[MAXN];
int dist[MAXN][10005]; //min_d_to_i_spend_j
int K,N,R,S,D,L,T;
void djstla()
{
for(int i=1; i<=N; i++)
d[i] = inf;
for(int i=1; i<=N; i++)
for(int j=0; j<10005; j++)
dist[i][j] = inf;
d[1] = 0;
Q.push((Node){1,0,0});
while(!Q.empty())
{
Node e = Q.top(); Q.pop();
int v = e.city;
if(v == N)
return;
for(int idv=0; idv<G[v].size(); idv++)
{
int to = G[v][idv].city;
int nt = e.t + G[v][idv].t;
int nc = e.c + G[v][idv].c;
if(nc > K || dist[to][nc] <= nt)
continue;
dist[to][nc] = nt;
if(d[to] > nt)
d[to] = nt;
Q.push((Node){to, nt, nc});
}
}
}
int main()
{
cin >> K >> N >> R;
for(int i=0; i<R; i++)
{
cin >> S >> D >> L >> T;
tmp.city = D; tmp.c = T; tmp.t = L;
G[S].push_back(tmp);
}
djstla();
if(d[N] == inf)
cout << -1 << endl;
else
cout << d[N] << endl;
return 0;
}