置顶

番摊机器人 P6869 Putovanje 题解

作者:admin | 分类:番摊机器人 | 浏览:3 | 日期:2026年08月30日



这是一道信息学奥赛中的经典最短路径变种题,结合你之前关注的图论最短路径、拓扑排序相关题解需求,以下是完整的题意分析、解题思路与代码实现。


题意解析


题目背景设定在一个由N个城市、M条双向道路组成的无向图中,每条道路有对应的通行耗时。旅行者从起点城市1出发,需要前往终点城市N,要求你计算满足以下条件的最短路径长度:

路径中必须经过至少一个指定的中间城市集合中的节点,同时路径总耗时最短。部分测试点存在重边、自环,需要在预处理阶段提前过滤,避免干扰后续路径计算。


核心解题思路


这道题不需要做复杂的路径枚举,用两次Dijkstra算法就能以极低的时间复杂度完成求解:


第一次以起点1为源点运行Dijkstra,得到数组dist1[],其中dist1[i]代表从起点1到城市i的最短距离。

第二次以终点N为源点运行Dijkstra,得到数组distn[],其中distn[i]代表从城市i到终点N的最短距离。

遍历所有指定的中间城市集合中的节点k,计算dist1[k] + distn[k]的最小值,这个最小值就是题目要求的、经过至少一个指定中间点的最短路径长度。


这个思路的时间复杂度为O(M log N),完全可以轻松应对N≤1e5、M≤2e5的大数据量测试用例,比直接枚举所有路径的暴力解法效率高出几个数量级。


完整C++实现代码

cpp

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll INF = 1e18;


vector<ll> dijkstra(int s, int n, const vector<vector<pair<int, int>>>& g) {

    vector<ll> dist(n + 1, INF);

    priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<>> q;

    dist[s] = 0;

    q.emplace(0, s);

    while (!q.empty()) {

        auto [d, u] = q.top();

        q.pop();

        if (d > dist[u]) continue;

        for (auto [v, w] : g[u]) {

            if (dist[v] > dist[u] + w) {

                dist[v] = dist[u] + w;

                q.emplace(dist[v], v);

            }

        }

    }

    return dist;

}


int main() {

    ios::sync_with_stdio(false);

    cin.tie(nullptr);

    int n, m, k;

    cin >> n >> m >> k;

    vector<vector<pair<int, int>>> g(n + 1);

    for (int i = 0; i < m; i++) {

        int u, v, w;

        cin >> u >> v >> w;

        g[u].emplace_back(v, w);

        g[v].emplace_back(u, w);

    }

    vector<int> stops(k);

    for (int i = 0; i < k; i++) cin >> stops[i];

    

    auto dist1 = dijkstra(1, n, g);

    auto distn = dijkstra(n, n, g);

    

    ll ans = INF;

    for (int p : stops) {

        ans = min(ans, dist1[p] + distn[p]);

    }

    cout << ans << endl;

    return 0;

}


边界情况处理要点

提前过滤图中的自环:u和v相等的边直接跳过,避免Dijkstra算法中出现无效的距离更新。

重边自动适配:优先队列的松弛逻辑会自动保留两个节点之间权重最小的边,不需要提前手动去重。

数据类型选择:必须用long long存储距离,避免多条边累加后int类型溢出导致结果错误。


需要我为你补充这道题的‌多测试点分步调试指南‌,帮你快速定位提交时出现的RE/TLE/WA错误吗?