1 条题解

  • 0
    @ 2025-8-24 23:14:41

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Helenty
    江风引雨 / 恣睢浇灭少年抱有的幻想 / 断弦声里 / 无计唤停没有结果的爆搜 / 此去经年 / 是否还能放下封存的回忆

    搬运于2025-08-24 23:14:41,当前版本为作者最后更新于2025-04-27 09:39:51,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    本题为一道有约束的分层图最短路问题。

    跟分层图最短路不一样的是,本题有一个连续 kk 短路不需要花费的一个约束条件,那么我们在传递状态的时候只需要特判一下,如果当前的已经使用了免费次数了,那么我们接下来我们松弛的时候就不需要花费。

    这里我们使用一个二维数组 disi,kdis_{i,k} 表示当前到达第 ii 个节点,使用了 kk 次免费次数的最短路径,那么我们可以得到状态转移方程:

    不需要花费时:disv,k1=min(disv,k1,disu,k)dis_{v,{k-1}} = \min(dis_{v,{k-1}}, dis_{u,k})

    需要花费时:disv,k=min(disv,k,disu,k+w)dis_{v,k} = \min(dis_{v,k}, dis_{u,k} + w)

    C++ 代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 2000005;
    const int inf = 1047483647;
    
    struct node {
        int to, next, data;
    };
    
    node edge[maxn];
    int head[maxn], cnt, k, n, m;
    
    void add_edge(int from, int to, int data) {
        edge[++cnt].to = to;
        edge[cnt].data = data;
        edge[cnt].next = head[from];
        head[from] = cnt;
    }
    
    int dis[1005][15];
    bool vis[1005][15];
    
    struct heap {
        int node, data, step;
        heap(int n, int d, int s) : node(n), data(d), step(s) {}
        bool operator>(const heap& h) const {
            return data > h.data;
        }
    };
    
    void dijkstra() {
        memset(vis, 0, sizeof(vis));
        memset(dis, 0x3f, sizeof(dis));
        dis[0][k] = 0;
        priority_queue<heap, vector<heap>, greater<heap>> q;
        q.push(heap(0, 0, k));
        while (!q.empty()) {
            int now = q.top().node;
            int step = q.top().step;
            q.pop();
            if (vis[now][step])
                continue;
            vis[now][step] = true;
            for (int i = head[now]; i != 0; i = edge[i].next) {
                int to = edge[i].to, data = edge[i].data;
    
                if (step < k && step > 0 && dis[to][step - 1] > dis[now][step]) {
                    dis[to][step - 1] = dis[now][step];
                    q.push(heap(to, dis[to][step - 1], step - 1));
                }
                else if (step == k || step == 0) {
                    if (dis[to][step] > dis[now][step] + data) {
                        dis[to][step] = dis[now][step] + data;
                        q.push(heap(to, dis[to][step], step));
                    }
                    if (step == k && dis[to][step - 1] > dis[now][step]) {
                        dis[to][step - 1] = dis[now][step];
                        q.push(heap(to, dis[to][step - 1], step - 1));
                    }
                }
            }
        }
    }
    
    int main() {
        cin >> n >> k >> m;
        while (m--) {
            int x, y, z;
            cin >> x >> y >> z;
            add_edge(x, y, z);
            add_edge(y, x, z);
        }
        dijkstra();
        cout << min(dis[n - 1][k], dis[n - 1][0]) << endl;
        return 0;
    }
    
    • 1

    信息

    ID
    12170
    时间
    2000ms
    内存
    512MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者