Magical Girl Haze(dij算法优化dp)

本文介绍了一位名叫Haze的魔法少女如何使用优化后的Dijkstra算法解决国家中城市间最短路径问题。给定N个城市,M条道路和K条可变为0距离的道路,Haze要从城市1出发前往城市N,目标是找到最小总距离。文章通过样例输入和输出解释了问题设置,并强调理解Dijkstra算法核心是关键,提供AC代码帮助读者理解实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

There are NNN cities in the country, and MMM directional roads from uuu to v(1≤u,v≤n)v(1\le u, v\le n)v(1≤u,v≤n). Every road has a distance cic_ici​. Haze is a Magical Girl that lives in City 111, she can choose no more than KKK roads and make their distances become 000. Now she wants to go to City NNN, please help her calculate the minimum distance.

Input

The first line has one integer T(1≤T≤5)T(1 \le T\le 5)T(1≤T≤5), then following TTT cases.

For each test case, the first line has three integers N,MN, MN,M and KKK.

Then the following MMM lines each line has three integers, describe a road, Ui,Vi,CiU_i, V_i, C_iUi​,Vi​,Ci​. There might be multiple edges between uuu and vvv.

It is guaranteed that N≤100000,M≤200000,K≤10N \le 100000, M \le 200000, K \le 10N≤100000,M≤200000,K≤10,
0≤Ci≤1e90 \le C_i \le 1e90≤Ci​≤1e9. There is at least one path between City 111 and City NNN.

Output

For each test case, print the minimum distance.

样例输入

1
5 6 1
1 2 2
1 3 4
2 4 3
3 4 1
3 5 6
4 5 2

样例输出

3

题目来源

ACM-ICPC 2018 南京赛区网络预赛

哇塞!我居然A 了。

苦于对dijstra算法的不理解,或者说理解的不是那么透彻,一直处于很难受的状态,导致这道题迟迟没有动,直到昨天上课时终于明白了每一次push进去的都是(当前通过枚举过的点(就是所谓的放到了集合中的点)所能够影响到的)当前的的点 的 最短路。

而利用最短路的思想,那我们每一次push进去的也是到达这个点目前已经换了j次的最优的情况,每一次枚举的点也都是dis(就是d[i][j])最小的点,通过这些已经算到了kk(就是算到这个点的时候已经删掉了kk条边)此时的最小的,那么当前这个状态就可以影响其他的还没有被更新的状态。每一种状态都push进去,就能算出来了。

最重要的是对jdijstra算法的理解。

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=100010;
const int maxm=200010;
int head[maxn];
int cnt;
int vis[maxn][12];
int n,m,k;
int d[maxn][12];
struct node
{
    int to,next,val;
}G[maxm];
void add(int a,int b,int val){
    G[++cnt].to=b;
    G[cnt].next=head[a];
    G[cnt].val=val;
    head[a]=cnt;
}
void init(){
    cnt=0;
    memset(head,-1,sizeof(head));
    memset(vis,false,sizeof(vis));
}
struct Node{
    int dis,to,k;
    Node(int dis,int to,int k):dis(dis),to(to),k(k){};
    bool operator < (const Node &a)const{
        return dis>a.dis;
    }
};
int dij(){
    priority_queue<Node>Q;
    for(int i=0;i<=k;i++)
        d[1][i]=0;

    Q.push(Node(0,1,0));

    while(!Q.empty()){
        Node x=Q.top();
        Q.pop();

        int to=x.to;
        int dis=x.dis;
        int kk=x.k;

        if(vis[to][k])
            continue;
        for(int i=head[to];i!=-1;i=G[i].next){
            int v=G[i].to;

          ///  cout<<"v:"<<v<<endl;

            for(int j=kk;j<=k;j++){
          ///          cout<<"&&&:"<<d[v][j]<<endl;
          ///          cout<<"Xiao:"<<d[to][j]<<endl;
                if(d[v][j]>d[to][j]+G[i].val){///不删
                    d[v][j]=d[to][j]+G[i].val;
       ///             cout<<"v:"<<v<<"   j:"<<j<<"   "<<d[v][j]<<endl;
                    Q.push(Node(d[v][j],v,j));
                }
                if( j>=1 &&d[v][j]>d[to][j-1]){///删
                    d[v][j]=d[to][j-1];
                     Q.push(Node(d[v][j],v,j));
                }
            }
        }
    }
}
int main()
{
    int t,a,b,c;
   /// freopen("r.txt","r",stdin);
    scanf("%d",&t);
    while(t--){
        init();
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
        }
        memset(d,INF,sizeof(d));

        dij();

        int ans=999999999;
        for(int i=0;i<=k;i++){
            ans=min(d[n][i],ans);
       ///     cout<<d[n][i]<<endl;
        }
        printf("%d\n",ans);
    }
    return 0;
}
/*
1
5 6 1
1 2 2
1 3 4
2 4 3
3 4 1
3 5 6
4 5 2
*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值