Magical Girl Haze(dij算法优化dp)

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
*/

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值