• 洛谷——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
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    (2).net体系
    (1)php开篇常识
    java基础知识-xx
    java基础知识-字符串与数组
    java基础知识-流程控制
    小明的喷漆计划
    加分二叉树
    括号序列
    P1045
    胖男孩
  • 原文地址:https://www.cnblogs.com/song-/p/9687933.html
Copyright © 2020-2023  润新知