• P1462 通往奥格瑞玛的道路【最大值中的最小】


    题目

    https://www.luogu.com.cn/problem/P1462

    题目背景

    在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量

    有一天他醒来后发现自己居然到了联盟的主城暴风城

    在被众多联盟的士兵攻击后,他决定逃回自己的家乡奥格瑞玛

    题目描述

    在艾泽拉斯,有n个城市。编号为1,2,3,...,n。

    城市之间有m条双向的公路,连接着两个城市,从某个城市到另一个城市,会遭到联盟的攻击,进而损失一定的血量。

    每次经过一个城市,都会被收取一定的过路费(包括起点和终点)。路上并没有收费站。

    假设1为暴风城,n为奥格瑞玛,而他的血量最多为b,出发时他的血量是满的。

    歪嘴哦不希望花很多钱,他想知道,在可以到达奥格瑞玛的情况下,他所经过的所有城市中最多的一次收取的费用的最小值是多少

    输入格式

    第一行3个正整数,n,m,b。分别表示有n个城市,m条公路,歪嘴哦的血量为b。

    接下来有n行,每行1个正整数,fi。表示经过城市i,需要交费fi元。

    再接下来有m行,每行3个正整数,ai,bi,ci(1<=ai,bi<=n)。表示城市ai和城市bi之间有一条公路,如果从城市ai到城市bi,或者从城市bi到城市ai,会损失ci的血量。

    输出格式

    仅一个整数,表示歪嘴哦交费最多的一次的最小值。

    如果他无法到达奥格瑞玛,输出AFK。

     分析

    这个题极其的……

    他所经过的所有城市中最多的一次收取的费用的最小值是多少:翻译如下:

    他可能有多条路径能够回城,那么求的就是这些路径中的每一条路径 经过的城市中收费最多的数字,现在要求这个数字最小可以是多少

    思路

    至于在路上他的血够不够,我们可以将路上失去的血量视为路径的长度,然后使用Dijkstra来判断他的血够不够回城

    接下来的问题就是寻找最小值的问题了

    具体的思路就是我们设置一个花费最大值变量cost,它必须是一条可行路径上费用最大的值,该路径上节点的费用必须比它小

    在使用Dijkstra判断血够不够的同时来判断该路径上有没有节点的费用比cost大,有的话说明我们自己设得这个cost值偏大,于是把cost改小一点继续。

    这样一来初步得思路就是我们让cost从1遍历到所有节点费用的最大值,一旦不存在节点的费用比cost大,那么此时的cost就是多条可行路径中经过城市中收费最多的数字里最小的一个,也就是最终的答案

    但是cost从1遍历到所有节点费用的最大值,每遍都要执行一次Dijkstra,可能会超时,所以我们使用二分搜索,来加快cost的确定速度

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cstring>
    #include<queue>
    #define inf 0x3f3f3f3f 
    #define maxn 10001
    #define maxm 50001
    using namespace std;
    struct edge
    {
        int to;
        int dis;
        int next;
    }e[maxm*2];
    struct node
    {
        int dis;
        int pos;
        bool operator<(const node &x)const
        {
            return dis > x.dis;
        }
    };
    int n, m, b;
    int bb[maxn], cc[maxn], head[maxn], dis[maxn], vis[maxn], cnt = 0;
    void addedge(int u, int v, int  w)
    {
        cnt++;
        e[cnt].dis = w;
        e[cnt].to = v;
        e[cnt].next = head[u];
        head[u] = cnt;
    }
    int check(int cost)
    {
        if (cost < bb[1]||cost<bb[n])return 0;//由于是从起点出发,到终点结束,如果cost一开始就比这两个点的费用小,那么cost就不是该路径中收费最多的,直接返回false
        memset(dis, inf, sizeof(dis));
        memset(vis, 0, sizeof(vis));
        dis[1] = 0;
        /*for (long long i = 1; i <= n; i++)
            if (bb[i]>cost)vis[i] = true;
            else vis[i] = false;*/
        priority_queue<node>q;
        q.push({0,1});
        while (!q.empty())
        {
            int x = q.top().pos; q.pop();
            if (vis[x])continue;
            vis[x] = 1;
            for (int i = head[x]; i; i = e[i].next)
            {
                int y = e[i].to;
                if (bb[y]>cost)continue;//因为下面的if是使用节点x作为中转节点来更新起点s到其它点(y)的距离的,所以要判断y点的费用是不是比cost小(保证cost的费用是在最大的)
                if (dis[y]>dis[x] + e[i].dis)
                {
                    dis[y] = dis[x] + e[i].dis;
                    q.push({ dis[y],y });        
                }
            }
        }
        if (dis[n] <= b)return 1;//当该条路径完毕后,看看需要的最小血量与人拥有的血量大小关系,判断能不能活着回去
        else return 0;
    }
    
    int main()
    {
        scanf("%d%d%d", &n, &m, &b);
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &bb[i]);
            cc[i] = bb[i];
        }
        sort(cc + 1, cc + n + 1);//二分要排序
        for (int i = 0; i < m; i++)
        {
            int ta, tb, tc;
            scanf("%d%d%d", &ta, &tb, &tc);
            addedge(ta, tb, tc);
            addedge(tb, ta, tc);
        }
        int l = 1, r = n, mid;
        int ans = -1;
        while (l <= r)
        {
            mid = (l + r) / 2;
            if (check(cc[mid]))
            {
                ans = cc[mid];
                r = mid - 1;
            }
            else l = mid + 1;
        }
        if (ans == -1)printf("AFK
    ");
        else printf("%lld", ans);
    
    }
  • 相关阅读:
    centos7 安装 nginx
    centos 关闭防火墙
    springcloud + nacos + mybatis ,增加seata分布式事务
    docker 运行 seata-server 配置nacos
    分布式事务4种方式,通俗易解篇
    主键字段报错doesn't have a default value (mybatis)
    模拟部署一个前后端分离的项目
    nginx配置接口转发路径
    前端部署后出现白板异常
    nodeJs的升降级(win10下)
  • 原文地址:https://www.cnblogs.com/Jason66661010/p/13143906.html
Copyright © 2020-2023  润新知