OneCoder Avatar
OneCodercoderli.com · 955 篇博文
八级

C++ 算法考级专栏

真题分析、矩阵探测、递归回溯与基础语法

🎨 视觉封面

【反向瓶颈最短路与Dijkstra最晚发车时间】GESP八级 / CSP-S 题解:luogu-P17462 [GESP202609 八级] 末班车

📅 2026-09-15·✍️ OneCoder·计算中...·⏱️ 8 分钟
#GESP#C++#GESP八级#CSP-S#高级图论#最短路#Dijkstra#离线处理#真题#2026年9月#GESP202609

CCF GESP 2026年9月认证(第十五次认证)C++ 八级试题,洛谷 P17462。本题严格遵循 CCF GESP 官方大纲规范,重点考察反向瓶颈最短路与Dijkstra最晚发车时间。题目逻辑严密,模型典型,是深入理解与掌握信奥核心考点的经典范例。

P17462 [luogu-P17462 [GESP202609 八级] 末班车]

🔗 洛谷原题传送门P17462

题目要求

题目描述

城市有 nn 个地铁站,mm 条单向线路。第 ii 条线路最晚发车时间 lil_i,运行时间 tit_i,每分钟均有列车发出。 有 qq 组询问:给出起点 xx、终点 yy 和出发时间 ss,判断从 xx 于时刻 ss 出发能否到达 yy

输入格式

第一行三个正整数 n,m,qn, m, q。 接下来 mm 行每行四个整数 ui,vi,li,tiu_i, v_i, l_i, t_i。 接下来 qq 行每行三个整数 xi,yi,six_i, y_i, s_i

输出格式

输出 qq 行,能到达输出 Yes,否则输出 No

输入输出样例

样例输入 #1
TEXT
3 4 5
1 2 3 3
2 3 5 2
3 1 4 1
1 3 0 6
1 3 2
2 1 2
2 1 3
3 2 2
3 2 3
样例输出 #1
TEXT
Yes
Yes
No
Yes
No

说明/提示

1n500,1m1000,1q5×1051 \le n \le 500, 1 \le m \le 1000, 1 \le q \le 5 \times 10^5


题目分析与解题思路

  1. 单调性与瓶颈最晚出发时间: 由于乘客可以在站点等待,若时刻 ss 能到达,则对于任何 s<ss' < s 也能到达。因此对于任意起点 xx 和终点 yy,存在一个最晚允许出发时间 L[x][y]L[x][y],使得可行条件为 sL[x][y]s \le L[x][y]
  2. 逆向动态规划与最大化 Dijkstran500n \le 500 极小,我们可以枚举终点 yy
    • 从终点 yy 出发在反向边上跑最大化 Dijkstra;
    • 设到达点 vv 能够继续前往 yy 的最晚时刻为 curdcur_d
    • 对于原向边 uvu \to v(最晚发车 ll,运行 tt),若在时刻 xx 离开 uu,到达 vvx+tx + t。要求 xlx \le lx+tcurdx + t \le cur_d,因此从 uu 最晚出发时刻为: nxtd=min(l,curdt)nxt_d = \min(l, cur_d - t)
    • 使用大根堆不断拓展松弛最大的可出发时刻 L[u][y]L[u][y]
  3. 单次询问 O(1)\mathcal{O}(1) 回答: 预处理全源最晚出发时间仅需 n×O(mlogn)500×1000×94.5×106n \times \mathcal{O}(m \log n) \approx 500 \times 1000 \times 9 \approx 4.5 \times 10^6 次运算(几十毫秒)。之后 5×1055 \times 10^5 次询问直接 O(1)\mathcal{O}(1) 比较输出,整体高效平稳通过!

完整参考代码 (C++11)

CPP
/**
 * Problem: luogu-P17462
 * Standard: C++11 (CCF GESP 官方大纲规范)
 * Author: OneCoder
 */

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

struct RevEdge {
    int u;
    long long l;
    long long t;
};

const long long INF = 2e18;
long long max_depart[505][505];

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

    int n, m, q;
    if (!(cin >> n >> m >> q)) return 0;

    vector<vector<RevEdge>> rev_adj(n + 1);
    for (int i = 0; i < m; ++i) {
        int u, v;
        long long l, t;
        cin >> u >> v >> l >> t;
        rev_adj[v].push_back({u, l, t});
    }

    // 初始化全源可达最晚时刻表
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            max_depart[i][j] = -1;
        }
    }

    // 对每个终点 y 跑反向最大化 Dijkstra
    for (int y = 1; y <= n; ++y) {
        priority_queue<pair<long long, int>> pq;
        max_depart[y][y] = INF;
        pq.push({INF, y});

        while (!pq.empty()) {
            auto top = pq.top();
            pq.pop();
            long long cur_d = top.first;
            int v = top.second;

            if (cur_d < max_depart[v][y]) continue;

            for (const auto& edge : rev_adj[v]) {
                int u = edge.u;
                long long nxt_d = min(edge.l, cur_d - edge.t);
                if (nxt_d >= 0 && nxt_d > max_depart[u][y]) {
                    max_depart[u][y] = nxt_d;
                    pq.push({nxt_d, u});
                }
            }
        }
    }

    // O(1) 快速回答每个询问
    for (int i = 0; i < q; ++i) {
        int x, y;
        long long s;
        cin >> x >> y >> s;
        if (s <= max_depart[x][y]) {
            cout << "Yes\n";
        } else {
            cout << "No\n";
        }
    }

    return 0;
}

考点归纳与备考建议

  1. 考纲匹配度:严格对标 CCF GESP 八级考纲重点,绝不超纲,注重基础算法与逻辑建模规范;
  2. 规范防范:所有代码严格以 C++11 标准编译运行,针对整数溢出、边界判断、空状态均做了详尽严整的防御性处理。
💡 OneCoder 资源指引

所有代码开源上传至 GitHub:yummy-code 仓库 · GESP 专题站:GESP WIKI

🤝 技术交流与答疑

欢迎加入:C++ GESP/CSP 考级答疑群(688906745)Java/Python交流群(982860385),点击可直接加群。

📚

猜你想读 · 相关文章推荐

OneCoder

OneCoder (lihongzheshuai)

一个中年人的自留地,记录学习 C++、GESP/NOI、Java、Python 与算法架构的心得体会。本站唯一网址:coderli.com

💬 读者留言与交流

0 条讨论
✨ 支持 Markdown 语法格式
还没有留言,快来成为第一个讨论者吧!