[LuoguP1462]通往奥格瑞玛的道路

题目链接

题意简述:现在有一个图,每经过一个点就会交钱,走一条路就会扣血。在血量>0的前提下,要从1走到n点,并且要求路径上交钱的最大值最小。

解题思路:首先最大值最小,我们选择二分。目前有两个限制条件,血量与金钱。我们选择二分金钱,因为二分金钱就可以将一部分的城市排除在外,但二分血量不行(扣血是累加的,而金钱只是单个点,所以删点比删边更好了)。那么二分了金钱之后限制了部分城市不能走,二分对应的check就用dijistra,跑一遍可以去的城市中的最短路(路上扣血作为边权),此时我们可以求得扣血最少,再与总血量进行比较,比总血量少就是一个可行解,继续二分看一看是否有更优的答案。 至于没有解则是不对城市进行限制都无法活着回去。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<fstream>
#include<queue>
using namespace std;
int read(){
    int res=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        res=res*10+(ch-'0');
        ch=getchar();
    }
    return res*f;
}
const int MAXN=100005;
int n,m,b,f[MAXN],head[MAXN],ne[MAXN],to[MAXN];
int c[MAXN],tot,money,vis[MAXN],ans;
priority_queue <pair<int,int> > q;
long long d[MAXN];
void add(int x,int y,int u){
    to[++tot]=y;
    c[tot]=u;
    ne[tot]=head[x];
    head[x]=tot;
}
bool dijistra(int max_money){
    memset(d,127/3,sizeof(d));
    memset(vis,0,sizeof(vis));
    d[1]=0;vis[1]=1;
    q.push(make_pair(0,1));
    while(!q.empty()){
        int u=q.top().second;
        q.pop();
        //vis[u]=0;
        for(int i=head[u];i;i=ne[i]){
            int v=to[i];
            if(f[v]>max_money||f[u]>max_money)continue;
            if(d[v]>d[u]+c[i]){
                d[v]=d[u]+c[i];
                if(!vis[v]){
                    vis[v]=1;
                    q.push(make_pair(-d[v],v));
                }
            }
        }
    }
    if(d[n]<b)return 1;
    else return 0;
}
int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    n=read();m=read();b=read();
    int l,r;
    for(int i=1;i<=n;++i){
        f[i]=read();
        r=max(f[i],r);
    }
    l=0;
    int a,b,c;
    for(int i=1;i<=m;++i){
        a=read();b=read();c=read();
        add(a,b,c);
        add(b,a,c);
    }
    if(!dijistra(1<<30)){
        printf("AFK");
        return 0;
    }
    r++;
    while(l<r){
        int mid=(l+r)>>1;
        if(dijistra(mid)){
            r=mid;
        }
        else {
            l=mid+1;
        }
    }
    printf("%d",l);
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/clockwhite/p/11825294.html