题解 P1462 【通往奥格瑞玛的道路】

题解-P1462 通往奥格瑞玛的道路

题目意思

题目意思很简单,就是你要从,你有的血量,每次从一个城市到另一个城市会消耗的血量,每个城市需要花的费用。现在问你当你的时,他所经过的所有城市中最多的一次收取的费用的最小值是多少。

算法思路

题目要求我们求最小值显然想到用二分求解呀。我们直接二分答案。但是需要注意的是:当你二分完后,但不一定而分出了答案,所以要对答案进一不验证,就是判断当你血量还是大于时是否达到了城市。在的时候,对于 或者 ,直接掉,然后对于即可。

代码实现

#include <bits/stdc++.h>
#define re register
#define int long long 
using namespace std;

const int maxn=1e5+5,maxm=5e5+5;
struct nood {
    int nex,to,w;
} e[maxm];
int head[maxn],dis[maxn],vis[maxn];
int n,m,b,cnt,ans,now,maxf,f[maxn],ff=0;

inline void add_edge(int u,int v,int len) {
    e[++cnt].nex=head[u];
    head[u]=cnt;
    e[cnt].to=v;
    e[cnt].w=len;
}
//前向星连边
inline int read() {
    int sum=0; char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) sum=sum*10+ch-'0',ch=getchar();
    return sum;
}
//快读
inline bool spfa(int x) {
    queue<int>ma;
    memset(vis,0,sizeof(vis));
    memset(dis,0x7f,sizeof(dis));
    ma.push(1),dis[1]=0,vis[1]=1;
    for ( re int i=1;i<=n;i++ ) 
        if(f[i]>x) vis[i]=1;
    //对于那些mid<f[i]的点标记为1
    while(!ma.empty()) {
        int u=ma.front(); 
        ma.pop(); 
        vis[u]=0;
        for ( re int i=head[u];i;i=e[i].nex ) {
            int v=e[i].to;
            if(dis[v]>dis[u]+e[i].w) {
                dis[v]=dis[u]+e[i].w;
                if(!vis[v]) {
                    vis[v]=1;
                    ma.push(v);
                }
            }
        }
    }//普通的最短路spfa
    if(dis[n]>b) return false;
    ff=1;
    return true;
    while(ma.size()) ma.pop();
}

signed main() {
    n=read(),m=read(),b=read();
    for ( re int i=1;i<=n;i++ ) 
        f[i]=read();
    for ( re int i=1;i<=m;i++ ) {
        int u=read(),v=read(),z=read();
        add_edge(u,v,z);
        add_edge(v,u,z);
    }
    int l=0,r=1e10;
    while(l<=r) {
        int mid=(l+r)/2;
        if(mid<f[n]||mid<f[1]) {
            l=mid+1;
            continue;
        }
        //对于而二分出的值小于f[1]或者f[n]直接跳过,并且l++,不l++会进入死循环。
        if(spfa(mid)) r=mid-1,ans=mid;
        else l=mid+1;
    }
    if(ff==0 && !spfa(ans)) 
        return printf("AFK\n"),0;
    //如果ff到达标记还是0,并且当前答案还是不对,输出AFK
    printf("%lld\n",ans);
    return 0;
}

总结

这道题目其实很简单,就是二分+,仔细想一想肯定能够的。

全部评论

相关推荐

乐观的打工人前程似锦:怎么说呢🤔️,学历够,专业技能看起来也有那么回事,就是项目会不会差点?dji更喜欢较为复杂的工程落地的项目吧?如果有一些title的项目就更好了。有实习也是加分项,搞过神经网络应该也是加分项。进面应该可以,还是要看技术过硬
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务