ACM-ICPC 2018 南京赛区网络预赛 L Magical Girl Haze(分层图最短路)

85 篇文章 2 订阅
15 篇文章 0 订阅

Magical Girl Haze

问题分析

题意:最多可以将 m m 条有向边中的k条边的权值变为 0 0 ,问1 n n 的最短距离。
题解:首先建立k+1层相同的图,其中 k k 个间隔代表k次机会,将对于每一条边 (u,v) ( u , v ) ,我们从当前层往底层建立一条权值为 0 0 的单向边(单向边保证不会返回上一层)。然后跑多一维的dijkstra就可以了。

代码

#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int N = 100010;
bool vis[N][11];
LL dist[N][11];
struct node {
    int x, k;
    LL v;

    node(int a, int b, LL v) : x(a), k(b), v(v) {}

    friend bool operator<(const node &a, const node &b) {
        return a.v > b.v;
    }
};
vector<node> E[N];

int main() {
    int T;
    //freopen("in.txt","r",stdin);
    scanf("%d", &T);
    while (T--) {
        memset(vis, 0, sizeof vis);
        int n, m, k, s, t, x, y, z;
        LL ans = 1e15;
        scanf("%d%d%d", &n, &m, &k);
        s = 0, t = n - 1;
        for (int i = 0; i <= n; ++i)
            E[i].clear();
        for (int i = 0; i < m; i++) {
            scanf("%d%d%d", &x, &y, &z);
            x--, y--;
            E[x].push_back(node(y, 0, z));
        }
        priority_queue<node> q;
        memset(dist, 0x3f, sizeof(dist));
        dist[s][0] = 0;
        q.push((node) {s, 0, 0});
        while (!q.empty()) {
            node now = q.top();
            q.pop();
            if (vis[now.x][now.k])
                continue;
            vis[now.x][now.k] = 1;
            int len = E[now.x].size();
            for (int i = 0; i < len; ++i) {
                node nxt = E[now.x][i];
                if (dist[now.x][now.k] + nxt.v < dist[nxt.x][now.k]) {
                    dist[nxt.x][now.k] = dist[now.x][now.k] + nxt.v;
                    q.push((node) {nxt.x, now.k, dist[nxt.x][now.k]});
                }
                if (dist[now.x][now.k] < dist[nxt.x][now.k + 1] && now.k < k) {
                    dist[nxt.x][now.k + 1] = dist[now.x][now.k];
                    q.push((node) {nxt.x, now.k + 1, dist[nxt.x][now.k + 1]});
                }
            }
        }
        for (int i = 0; i <= k; i++) ans = min(ans, dist[t][i]);
        printf("%lld\n", ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值