SP338ROADS题解--最短路变式

题目链接

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

分析

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

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

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

代码

#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;
}
posted @ 2018-09-14 18:44  Rye_Catcher  阅读(311)  评论(0编辑  收藏  举报