• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
PCMSFV
博客园    首页    新随笔    联系   管理    订阅  订阅

P1462 通往奥格瑞玛的道路

题面

解析

题面直接说了最大值最小,二分无疑
看到这题的应该都想到了最短路吧,但是一看又要管花费,还要管血量立马慌了,但是其实没有那么复杂

二分歪嘴哦经过城市单次交费最大值\(x\)(不是等会代码的x,这里只是便于书写),通过 Dijkstra算法 得到对于这个\(x\)的最小耗血,\(x\)越大能走的路一定不会变少,耗血自然不会少,等到能活下来且\(x\)最小,答案就出来了

代码

alt text

会被hack的代码,\(WA\), \(100pts\)

#include <bits/stdc++.h>

using namespace std;

constexpr int N = 5e4 + 2;

int n, m, b;
int v[N], d[N];
bool f[N];
vector<pair<int, int>> a[N];

inline void read() {
    cin >> n >> m >> b;
    for (int i = 1; i <= n; i++) {
        cin >> v[i];
    }
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        a[u].push_back({v, w});
        a[v].push_back({u, w});
    }
}

inline bool check(int mx) {
    for (int k = 1; k <= N; k++) {
        d[k] = (1 << 30);
    }
    memset(f, 0, sizeof f);
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
    q.push({0, 1});
    d[1] = 0;

    while (!q.empty()) {
        auto t = q.top();
        q.pop();
        int now = t.second;
        if (f[now]) continue;
        f[now] = true;
        for (auto i : a[now]) {
            int x = i.first, y = i.second;
            if (v[x] > mx) continue;
            if (d[x] > d[now] + y) {
                d[x] = d[now] + y;
                q.push({d[x], x});
            }
        }
    }

    int mi = d[n];
    if (b - mi >= 0)
        return true;
    else
        return false;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    read();
    int l = 0, r = 1e9;
    int ans = -1;
    while (l <= r) {
        int mid = (l + r) / 2;
        if (check(mid))
            r = mid - 1, ans = mid;
        else
            l = mid + 1;
    }

    if (ans == -1)
        cout << "AFK";
    else
        cout << ans;
    return 0;
}
关于hack

上面的代码,没有考虑原点是否会超收费!

\(AC\),\(100pts\)

#include <bits/stdc++.h>

using namespace std;

constexpr int N = 5e4 + 2;
#define int long long

int n, m, b;
int v[N], d[N];
bool f[N];
vector<pair<int, int>> a[N];

inline void read() {
    cin >> n >> m >> b;
    for (int i = 1; i <= n; i++) {
        cin >> v[i];
    }
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        a[u].push_back({v, w});
        a[v].push_back({u, w});
    }
}

inline bool check(int mx) {
    if (v[1] > mx) return false;
    for (int k = 1; k <= N; k++) {
        d[k] = (1 << 30);
    }
    memset(f, 0, sizeof f);
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
    q.push({0, 1});
    d[1] = 0;

    while (!q.empty()) {
        auto t = q.top();
        q.pop();
        int now = t.second;
        if (f[now]) continue;
        f[now] = true;
        for (auto i : a[now]) {
            int x = i.first, y = i.second;
            if (v[x] > mx) continue;
            if (d[x] > d[now] + y) {
                d[x] = d[now] + y;
                q.push({d[x], x});
            }
        }
    }

    int mi = d[n];
    if (b - mi >= 0)
        return true;
    else
        return false;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    read();
    int l = 0, r = 1e9;
    int ans = -1;
    while (l <= r) {
        int mid = (l + r) / 2;
        if (check(mid))
            r = mid - 1, ans = mid;
        else
            l = mid + 1;
    }

    if (ans == -1)
        cout << "AFK";
    else
        cout << ans;
    return 0;
}

做题经验总结

  1. “最大值最小 / 最小值最大”
    优先想到二分答案,这是固定套路。

  2. 二分 + 最短路
    先明确限制条件:哪些点、哪些边可以走,不要漏约束。

  3. 起点、终点也是路径的一部分
    必须一起判断是否合法,不要默认起点一定能走。
    漏判这里,几乎必 WA / 被 hack。

  4. Dijkstra 易错三要点

    • 一定要写 q.pop()
    • 距离开 long long 防溢出
    • vis 数组每次 check 都要清空
  5. 无穷大赋值建议
    memset 对 long long 容易出错,
    直接循环赋 1e18 最稳妥。

  6. 格式分不能丢
    题目要求输出 AFK 之类的字符串,一定要写对。

  7. 被 hack 多半是漏边界
    常见坑:起点、终点、0 权、重边、自环、不连通。

一句话核心

路径上的点限制,起点终点也算点,必须一起判合法。


看懂?点赞?

posted on 2026-04-04 11:09  PCMSFV  阅读(8)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3