第36650题 组合题
完善程序(第一题):分层图最短路

(分层图最短路)给定一个含 n 个点、m 条边的无向连通图,边权均为非负整数。你有一个特殊道具:在整个过程中,最多可以把 K 条经过的边变为“免费边”,即第一次经过这些边时费用为 0(之后再经过仍按原费用计算)。点和边均允许重复经过。求从结点 1 到结点 n 的最小总费用。

以下代码求解了上述问题。它把“已经使用了多少次免费机会”作为状态的一维,在分层图上用堆优化的 Dijkstra 求最短路。试补全程序。

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;

const int MAXN = 100005;
const long long INF = (long long)4e18;

struct Edge { int to, w; };
struct Node {
    long long d; int u, k;
    bool operator<(const Node &o) const { return d > o.d; }
};

int n, m, K;
vector<Edge> g[MAXN];

int main() {
    scanf("%d%d%d", &n, &m, &K);
    for (int i = 1; i <= m; ++i) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        g[u].push_back({v, w});
        g[v].push_back({u, w});
    }
    vector<vector<long long>> dist(n + 1, vector<long long>(K + 1, INF));
    priority_queue<Node> pq;
    dist[1][0] = 0;
    pq.push({0, 1, ___①___});
    while (!pq.empty()) {
        Node cur = pq.top(); pq.pop();
        int u = cur.u, k = cur.k;
        if (___②___) continue;
        for (size_t t = 0; t < g[u].size(); ++t) {
            int v = g[u][t].to, w = g[u][t].w;
            if (dist[u][k] + w < dist[v][k]) {
                dist[v][k] = dist[u][k] + w;
                pq.push({dist[v][k], v, k});
            }
            if (___③___ && dist[u][k] < dist[v][k + 1]) {
                ___④___;
                pq.push({dist[v][k + 1], v, k + 1});
            }
        }
    }
    long long ans = INF;
    for (int k = 0; k <= K; ++k) ___⑤___;
    printf("%lld\n", ans);
    return 0;
}
{{ option.label }}
子题{{ index + 1 }} {{ child.type_label }}
{{ option.label }}
✓ 正确 ◐ 部分正确 ✗ 错误
程序运行统计
暂无判题统计
知识点:
提交{{ questionInfo.stats ? questionInfo.stats.submit_count : 0 }}次 正确率{{ statsAccuracy }}%
答案解析