洛谷——P1951 收费站_NOI导刊2009提高(2)

P1951 收费站_NOI导刊2009提高(2)

 

题目描述

在某个遥远的国家里,有n个城市。编号为1,2,3,…,n。

这个国家的政府修建了m条双向的公路。每条公路连接着两个城市。沿着某条公路,开车从一个城市到另一个城市,需要花费一定的汽油。

开车每经过一个城市,都会被收取一定的费用(包括起点和终点城市)。所有的收费站都在城市中,在城市间的公路上没有任何的收费站。

小红现在要开车从城市u到城市v(1<=u,v<=n)。她的车最多可以装下s升的汽油。在出发的时候,车的油箱是满的,并且她在路上不想加油。

在路上,每经过一个城市,她都要交一定的费用。如果某次交的费用比较多,她的心情就会变得很糟。所以她想知道,在她能到达目的地的前提下,她交的费用中最多的一次最少是多少。这个问题对于她来说太难了,于是她找到了聪明的你,你能帮帮她吗?

 

显然二分+SPFA

SPFA会超时,使用堆优化的SPFA

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define N 1010100
#define inf 0x7fffffff
#define LL long long
using namespace std;


LL n,m,S,T,s,val[N],tot,head[N],ans;
struct node {
    LL to,next,w;
} e[N];

void add(LL u,LL v,LL w) {
    e[++tot].to=v,e[tot].next=head[u],head[u]=tot,e[tot].w=w;
}

struct npde{
    int u;
    LL d;
    friend bool operator < (npde x,npde y){
        return x.d>y.d;
    }
};
priority_queue<npde>Q;
LL d[N];
bool vis[N];
void spfa() {
    memset(d,0x7f,sizeof(d));
    memset(vis,0,sizeof(vis));
    d[S]=0;
    vis[S]=1;
    Q.push((npde){S,0});
    while(!Q.empty()) {
        int u=Q.top().u,D=Q.top().d;
        Q.pop();
        vis[u]=0;
        for(LL i=head[u]; i; i=e[i].next) {
            LL v=e[i].to;
            if(d[v]>d[u]+e[i].w) {
                d[v]=d[u]+e[i].w;
                if(!vis[v]) vis[v]=1,Q.push((npde){v,d[v]});
            }
        }
    }
}

bool Spfa(LL X) {
    fill(d+1,d+1+n,inf);
    memset(vis,0,sizeof(vis));
    d[S]=0;
    vis[S]=1;
    Q.push((npde){S,0});
    while(!Q.empty()) {
        LL u=Q.top().u;
        Q.pop();
        vis[u]=0;
        for(LL i=head[u]; i; i=e[i].next) {
            LL v=e[i].to;
            if(d[v]>d[u]+e[i].w&&val[v]<=X) {
                d[v]=d[u]+e[i].w;
                if(!vis[v]) vis[v]=1,Q.push((npde){v,d[v]});
            }
        }
    }
    return d[T]<=s;
}

int main() {
    scanf("%lld%lld%lld%lld%lld",&n,&m,&S,&T,&s);
    for(LL i=1; i<=n; i++)
        scanf("%lld",&val[i]),val[0]=max(val[0],val[i]);
    for(LL u,v,w,i=1; i<=m; i++) {
        scanf("%lld%lld%lld",&u,&v,&w);
        add(u,v,w),add(v,u,w);
    }
    spfa();
    if(d[T]>s) printf("-1");
    else {
        LL l=val[S],r=val[0];
        while(l<=r) {
            LL mid=(l+r)/2;
            if(Spfa(mid)) ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2018-09-21 18:21  清风我已逝  阅读(219)  评论(0编辑  收藏  举报