ICPC网络赛 - Magical Girl Haze (DP+最短路)

Magical Girl Haze

题目链接: Magical Girl Haze

题意

给你一个图,N个节点,M条边,现在给你最多K次机会将一条边的权值变为0,求从1到N的最短路。 N<105,M<2105,K<=10 N < 10 5 , M < 2 ∗ 10 5 , K <= 10


思路

既然我们总共有K次机会修改,那么最显然的就是DP了,每次在进行最短路松弛时,增加一个状态

dis[v][k]=dis[u][k]+cost d i s [ v ] [ k ] = d i s [ u ] [ k ] + c o s t dis[v][k]=dis[u][k1] d i s [ v ] [ k ] = d i s [ u ] [ k − 1 ] 两个公式不段断进行松弛即可,这里需用迪杰斯特拉进行优化,这样复杂度为 O(KMlogv) O ( K M l o g v )


代码

#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(ll i = (ll)j;i <= (ll)k;i ++)
#define per(i,j,k) for(ll i = (ll)j;i >= (ll)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back

typedef double db;
typedef long long ll;
const ll MAXN = (ll)1e5+7;
const ll INF = (ll)1e18;

inline int read() { int c = 0, f = 1;char ch = getchar();
    while (ch < '0' || ch > '9') {if (ch == '-') f = -1;ch = getchar();}
    while (ch >= '0' && ch <= '9') {c = c * 10 + ch - '0';ch = getchar();}
    return c * f;
}

ll dis[MAXN][12];
int N,M,K;

struct Node{
    int to;
    ll co;
    int sta;
    Node(int to = 0,ll co = 0,int sta = 0):to(to),co(co),sta(sta){}
    bool operator < (const Node& a) const {
        return a.co < co;
    }
};

struct edge{
    int to,co;
    edge(int to = 0,int co = 0):to(to),co(co){}
};

vector<edge> E[MAXN];
bool vis[MAXN][12];

priority_queue<Node> qu;
inline ll djs() {
    while (!qu.empty())qu.pop();
    dis[1][0] = 0;
    qu.push(Node(1,0,0));

    ll ans = INF;
    while (!qu.empty()) {
        Node k = qu.top();qu.pop();
        //cout <<k.to << ',' << k.sta << endl;
        rep(i,0,E[k.to].size()-1) {
            int to = E[k.to][i].to;
            ll co = k.co + E[k.to][i].co;
            if (k.sta < K && k.co < dis[to][k.sta+1]) {
                qu.push(Node(to,k.co,k.sta+1));
                dis[to][k.sta+1] = k.co;
            }
            if (co < dis[to][k.sta]) {
                qu.push(Node(to,co,k.sta));
                dis[to][k.sta] = co;
            }
        }
    }
    ans = *min_element(dis[N],dis[N]+1+K);
    return ans;
}

int main()
{
    int T;
    T = read();
    while(T --) {
        N = read(),M = read(),K = read();
        rep(i,1,N) E[i].clear();
        rep(i,1,N) rep(j,0,K) dis[i][j] = INF;
        rep(i,1,M) {
            int x = read(),y = read(),w = read();
            E[x].pb(edge(y,w));
        }
        printf("%lld\n",djs());
    }
}
/*
2
3 3 1
1 2 1
2 3 1
1 3 1
*/
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值