SP338ROADS题解--最短路变式

题目链接

https://www.luogu.org/problemnew/show/SP338

分析

联想到不久前做过的一道题$Full$ $Tank$,感觉可以用优先队列做,于是写了$dijsktra$(非负权图不敢用$SPFA$了)

然后发现错了,想了挺久,发现它实际上是可以找$dis$更大的走以花费更少的钱,于是把$vis$数组和$dis$数组全去掉就A了

优先队列保证取出的距离是最短的,如果距离相同,那么钱数是最小的,所以第一次取出$n$时就是答案,跑得出乎意料的快

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <queue>
#define ll long long
#define ri register int
using std::min;
using std::max;
using std::priority_queue;
template <class T>inline void read(T &x){
x=0;int ne=0;char c;
while(!isdigit(c=getchar()))ne=c=='-';
x=c-48;
while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
x=ne?-x:x;return ;
}
const int maxn=10005;
const int inf=0x7fffffff;
struct Edge{
int ne,to,dis,co;
}edge[maxn];
int h[maxn],num_edge=0;
inline void add_edge(int f,int to,int d,int co){
edge[++num_edge].ne=h[f];
edge[num_edge].to=to;
edge[num_edge].dis=d;
edge[num_edge].co=co;
h[f]=num_edge;
}
struct Sta{
int ver,dis,c;
Sta(int x,int y,int z){ver=x,dis=y,c=z;}
bool operator <(const Sta &b)const{
return dis==b.dis?c<b.c:dis>b.dis;
}
};
int n,m,k;
inline void dij(){
Sta tmp=Sta{0,0,0};
int u,v,d,val,ans=inf;
priority_queue<Sta>q;
while(q.size())q.pop();
q.push(Sta(1,0,k));
while(q.size()){
tmp=q.top();q.pop();
u=tmp.ver,d=tmp.dis,val=tmp.c;
if(u==n){
ans=d;
break;
}
for(ri i=h[u];i;i=edge[i].ne){
v=edge[i].to;
if(val-edge[i].co>=0){
q.push(Sta(v,d+edge[i].dis,val-edge[i].co));
}
}
}
if(ans==inf)puts("-1");
else printf("%d\n",ans);
return ;
}
int main(){
int T,x,y,z,p;
read(T);
while(T--){
read(k),read(n),read(m);
num_edge=0;
memset(h,0,sizeof(h));
for(ri i=1;i<=m;i++){
read(x),read(y),read(z),read(p);
add_edge(x,y,z,p);
//add_edge(y,x,z,p);
}
dij();
}
return 0;
}