(题目蜜汁复制不下来...直接进入正题!然后我就会被发现我的题解巨短无比....羞愧)
算法标签:dijk
思路:
这题的难点在于高度的控制,其实因为他时间消耗都只会下降,所以当我们走到一定步数之后,其实每一段都是重复上升再走到0,周而复始。根据这个条件,我们可以根据他所走的权值,看出我们当前的高度,于是我们就可以根据权值推出高度,剩下的就是正常的dijk寻找最短路了!
以下代码:
#include<bits/stdc++.h> #define il inline #define LL long long #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; const int N=1e5+5,M=3e5+5;const LL inf=2e18; int n,m,x,h[N],head[N],ne[M<<1],w[M<<1],to[M<<1],cnt;LL d[N]; struct node{int x;LL d;bool operator<(const node&t1)const{return d>t1.d;};};priority_queue<node> q; il int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return f*x;} il void insert(int x,int y,int z){ne[++cnt]=head[x];head[x]=cnt;to[cnt]=y;w[cnt]=z;} il void dijk(){ q.push((node){1,d[1]}); while(!q.empty()){ node now=q.top();q.pop();if(d[now.x]!=now.d)continue; for(int i=head[now.x];i;i=ne[i]){ LL hh,ww=0;hh=max((LL)x-d[now.x],0ll)-(LL)w[i]; if(hh<0){ ww=-hh;if(max((LL)x-d[now.x],0ll)+ww>h[now.x])continue; } else if(hh>h[to[i]]){ ww=hh-h[to[i]]; } if(d[to[i]]>d[now.x]+(LL)w[i]+(LL)ww){ d[to[i]]=d[now.x]+(LL)w[i]+(LL)ww; q.push((node){to[i],d[to[i]]}); } } } } int main() { n=read();m=read();x=read();for(int i=1;i<=n;i++)h[i]=read(); for(int i=1;i<=m;i++){ int x=read(),y=read(),z=read();insert(x,y,z);insert(y,x,z); } for(int i=1;i<=n;i++)d[i]=inf;d[1]=0; dijk(); if(d[n]==inf)puts("-1"); else{ LL hh,ww=0;hh=max((LL)x-d[n],0ll);ww=abs(hh-h[n]); printf("%lld ",d[n]+ww); } return 0; }