2018.10.29-dtoj-4007-飞天鼠小E

(题目蜜汁复制不下来...直接进入正题!然后我就会被发现我的题解巨短无比....羞愧)

算法标签: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;
}
View Code
原文地址:https://www.cnblogs.com/Jessie-/p/9874627.html