zoukankan      html  css  js  c++  java
  • 洛谷 P1462 通往奥格瑞玛的道路 解题报告

    P1462 通往奥格瑞玛的道路

    题目背景

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

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

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

    题目描述

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

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

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

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

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

    输入输出格式

    输入格式:

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

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

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

    输出格式:

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

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

    说明

    对于60%的数据,满足(n≤200,m≤10000,b≤200)

    对于100%的数据,满足(n≤10000,m≤50000,b≤1000000000)

    对于100%的数据,满足(c_i≤1000000000)(f_i≤1000000000),可能有两条边连接着相同的城市。


    首先读懂题:他所经过的所有城市中 最多的一次收取的费用 的最小值是多少。

    意思就是他可能选择的某条路上有一个点,要交的保护费是所有中最多的。

    他要选一条路,让这个最多的保护费最小。

    很明显的二分答案的特征吧?

    每次比(mid)(二分的保护费)大的边删掉

    而损失血量其实就是边权,跑最短路即可

    不过题目有点没说清楚,如果刚好没血了到的是不算数的,有点坑。

    另外有一点,最好开(long) (long),不开的话,要控制不爆可能有点点难搞((0x3f)比十亿稍稍大一点)


    说一下自己智障的错误吧。。

    1. 前向星开边只开了(50000)个点,刚从(vector)转过来没有意识到双向边要开两倍。
    2. 忘记输出(AFK)了(这样的错误也能犯啊...)
    3. 二分时先把保护费排了个序离散,然后,然后我们就没管它了啊!!!(哭...呜呜呜)

    code

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #define ll long long
    using namespace std;
    const int N=10002;
    const int M=100002;
    ll max(ll x,ll y) {return x>y?x:y;}
    ll min(ll x,ll y) {return x<y?x:y;}
    struct Edge
    {
         ll to,next,w;
    }edge[M];
    ll head[N],cnt=0;
    ll n,m,b,f[N],f0[N];
    void add(ll u,ll v,ll w)
    {
        edge[++cnt].next=head[u];
        edge[cnt].to=v;
        edge[cnt].w=w;
        head[u]=cnt;
    }
    ll read()
    {
        ll x=0;char c=getchar();
        while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
        return x;
    }
    queue <int > q;
    ll vis[N],dis[N];
    bool check(ll c)
    {
        memset(vis,0,sizeof(vis));
        memset(dis,0x3f,sizeof(dis));
        vis[1]=1,dis[1]=0;
        q.push(1);
        while(!q.empty())
        {
            int u=q.front();
            vis[u]=0;
            q.pop();
            for(int i=head[u];i;i=edge[i].next)
            {
                int v=edge[i].to,w=edge[i].w;
                if(dis[v]>dis[u]+w&&f[v]<=c)
                {
                    dis[v]=dis[u]+w;
                    if(!vis[v])
                    {
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
        if(b<=dis[n]) return false;
        return true;
    }
    
    int main()
    {
        n=read(),m=read(),b=read();
        for(int i=1;i<=n;i++) f[i]=read(),f0[i]=f[i];
        sort(f0+1,f0+1+n);
        ll u,v,w;
        for(int i=1;i<=m;i++)
        {
            u=read(),v=read(),w=read();
            add(u,v,w),add(v,u,w);
        }
        ll l=1,r=n;
        if(!check(f0[r])) {printf("AFK
    ");return 0;}
        while(l<r)
        {
            int mid=l+r>>1;
            if(check(f0[mid]))
                r=mid;
            else
                l=mid+1;
        }
        printf("%lld
    ",f0[l]);
        return 0;
    }
    

    2018.5.13

  • 相关阅读:
    从通胀说起
    科技见欲迷人眼
    吃货在西安 之 粉丝羊血泡馍
    祝母亲大人福如东海长流水,寿比南山不老松
    久违的蓝调北京
    调和生活前的问题
    《N2CMS实例教程》第四讲:Article Template Page
    《N2CMS实例教程》前言
    《N2CMS实例教程》第一讲:开发环境
    Microsoft Sync Framework 学习实例1文件同步
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9033014.html
Copyright © 2011-2022 走看看