zoukankan      html  css  js  c++  java
  • [LuoguP1462]通往奥格瑞玛的道路($SPFA+$二分)

    #(mathcal{color{red}{Description}})

    (Link)

    有一个图,求其在(1-N)的最短路小于一个给定值下,点权最大值的最小值。

    #(mathcal{color{red}{Solution}})

    (emmm)这个题也是几天前做的……正在填坑(qwq)

    这道题虽然在(Luogu)上显示是和(color{cyan}{A Link})一个难度的,但是要明显简单很多好不好……

    正解的话,很显然要二分一个血量…… 因为二分(答案)是有套路的:

    1、求最……的……(一般不可以静态求)

    2、求什么就二分什么

    3、 一般是反着推,就是用二分出的结果去推条件是否满足,或者状态是否合法

    于是,二分交费,然后在(check)的时候,由于二分的是最大值,所以比二分的(x)大的就不走,小的可以走,以此为限制条件(SPFA),观察跑出来的最短路是否大于拥有的血量,大的话自然就不合法,小的话自然合法。然后就做完了(qwq)

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define ll long long
    #define to(k) e[k].to
    
    using namespace std ;
    const int MAXN = 62050 ;
    struct edge{
        ll to, next, v ;
    }e[MAXN << 1] ;
    queue<ll> q ;
    ll head[MAXN << 1], cnt, dist[MAXN], i, k, ct ;
    ll base[MAXN], l, r, mid, a, b, c, N, M, K, vis[MAXN], now ;
    
    inline void init(){
        memset(dist, 0x3f, sizeof(dist)), memset(vis, 0, sizeof(vis)) ;
        queue<ll> emt ; swap(q, emt), q.push(1), vis[1] = 1, dist[1] = 0  ;
    }
    inline bool check(ll x){
        init() ;
        while(!q.empty()){
            now = q.front(), q.pop(), vis[now] = 0 ;
            for(k = head[now]; k ; k = e[k].next){
                if(base[to(k)] > x) continue ;
                if(dist[to(k)] > dist[now] + e[k].v){
                    dist[to(k)] = dist[now] + e[k].v ;
                    if(!vis[to(k)]){
                        vis[to(k)] = 1 ;
                        q.push(to(k)) ;
                    }
                }
            }
        }
        if(dist[N] > K) return 0 ; return 1 ;
    }
    inline void add(int u, int v, int w){
        e[++cnt].to = v, e[cnt].v = w ;
        e[cnt].next = head[u], head[u] = cnt ;
    }
    int main(){
        cin >> N >> M >> K ;
        for(i = 1; i <= N; i ++) cin >> base[i] ;
        for(i = 1; i <= M; i ++){
            cin >> a >> b >> c ;
            add(a, b, c), add(b, a, c) ;
        }l = 0, r = 1000000000 ;
        while(l < r){
            mid = (l + r) >> 1 ;
            if(check(mid)) r = mid ;
            else  l = mid + 1 ;
        }
        if(l == 1000000000) cout << "AFK" ;
        else cout << l ;
    }
    
    

    幕后花絮:这个题我特别细心地判了(-1),结果让输出(AFK)……好吧人生就是这样的跌宕起伏(ORZ)……然后现在的我看二分答案就像我当年的我看快速幂一样,绝对不是不会,可以充分体现出我的“OI”思维没有多高……因为常人自然难以理解,(Coder)素质越高,理解起来越简单……现在的状态嘛…大概写出一份二分答案来问题不是很大,但是要做到稔熟于心,也还需要一段路要走啊(qwq)

  • 相关阅读:
    ESP8266 RTOS SDK烧写环境构建
    杂记:解决Android扫描BLE设备名称不刷新问题
    deviceMotion.userAcceleration加速度方向
    二、多功能提示框——MBProgressHUD
    一、初识CocoaPods——XCode的依赖库管理工具
    摄像机的控制
    DOTween 使用方法
    Unity依赖注入使用详解
    Unity中对SQL数据库的操作
    unity导弹算法 预计目标点
  • 原文地址:https://www.cnblogs.com/pks-t/p/9368186.html
Copyright © 2011-2022 走看看