zoukankan      html  css  js  c++  java
  • Luogu 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。

    6月离开机房准备期末考试的最后一道题。

    一个月之后才来写题解QAQ。

    题目设问为:最多的一次收取的费用的最小值是多少。那么就基本可以确定是二分。

    二分?题目设问求费用,那我们二分费用好了。

    左边界为l==1,右边界就是全部的点权之和。【这里注意开long long 】! 否则会wa3个点。

    void binary()
    {
        ll l=1,r=sum;
        while(l<r)
        {
            ll mid=(l+r)>>1;
            if(spfa_check(mid)) r=mid;
            else l=mid+1;
        }
        ans=l; 
    }

    最短路?我们求最短路的目的是看血量是否满足要求。在这里起点和终点都是确定的。

    在基本的最短路(这里用的是spfa)上加一个条件:走到的这个点的点权是否满足小于我们二分出的花费。

    跑完一遍,如果dis[n]小于血量,则可行,可继续二分。

            for(int i=head[x];i;i=edge[i].next)
            {
                int y=edge[i].to;
                if(dis[y]>dis[x]+edge[i].val&&f[y]<=cnt)
                {
                    dis[y]=dis[x]+edge[i].val;
                    if(visit[y]==0)
                    {
                        visit[y]=1;
                        q.push(y);
                    }
                }
            }

    跑最短路的时候记得每次都要初始化一下。

    无解判定?我们可以在最开始让花的费用等于inf,进行一遍spfacheck,在如此宽松的条件下都不可行,那必是无解了!输出AFK。

    code

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 int inf=0x3f3f3f3f;
     5 int n,m,b,tot,f[20000],u[20000],head[20000],dis[20000];
     6 bool visit[20000];
     7 ll ans,sum;
     8 struct node{
     9     int to,next,val;
    10 }edge[110000];
    11 void add(int x,int y,int z)
    12 {
    13     edge[++tot].to=y;
    14     edge[tot].val=z;
    15     edge[tot].next=head[x];
    16     head[x]=tot;
    17 }
    18 bool spfa_check(ll cnt)
    19 {
    20     memset(visit,0,sizeof(visit));
    21     queue<int>q;
    22     for(int i=1;i<=n;i++) dis[i]=inf;
    23     dis[1]=0;
    24     visit[1]=1;
    25     q.push(1);
    26     while(!q.empty())
    27     {
    28         int x=q.front();
    29         q.pop();visit[x]=0;
    30         for(int i=head[x];i;i=edge[i].next)
    31         {
    32             int y=edge[i].to;
    33             if(dis[y]>dis[x]+edge[i].val&&f[y]<=cnt)
    34             {
    35                 dis[y]=dis[x]+edge[i].val;
    36                 if(visit[y]==0)
    37                 {
    38                     visit[y]=1;
    39                     q.push(y);
    40                 }
    41             }
    42         }
    43     }
    44     if(dis[n]<b) return true;
    45     else return false;
    46 }
    47 void binary()
    48 {
    49     ll l=1,r=sum;
    50     while(l<r)
    51     {
    52         ll mid=(l+r)>>1;
    53         if(spfa_check(mid)) r=mid;
    54         else l=mid+1;
    55     }
    56     ans=l; 
    57 }
    58 int main()
    59 {
    60     scanf("%d%d%d",&n,&m,&b);
    61     for(int i=1;i<=n;i++) 
    62         scanf("%d",&f[i]),sum+=f[i];
    63     for(int i=1;i<=m;i++)
    64     {
    65         int x=0,y=0,z=0;
    66         scanf("%d%d%d",&x,&y,&z);
    67         if(x==y) continue;
    68         add(x,y,z);
    69         add(y,x,z);
    70     }
    71     if(!spfa_check(inf))
    72     {
    73         printf("AFK
    ");
    74         return 0;
    75     }
    76     binary();
    77     printf("%lld",ans);
    78     return 0;
    79 }
    View Code
  • 相关阅读:
    Altium Designer 快捷键,长期更新
    代码: 0x80131500:应用商店崩溃怎么修复
    (转)stm32cubeMx配置使用encoder编码器
    STM32 PWM注意事项
    转载 STM32 使用Cubemx 建一个USB(HID)设备下位机,实现数据收发
    STM32Cube填坑,ST link 下载一次以后无法下载
    SuperSocket 学习笔记-客户端
    python-kaggle之旅
    Leetcode刷题记(9)——移除元素
    Leetcode刷题记(8)——删除排序数组中的重复项
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9334514.html
Copyright © 2011-2022 走看看