2018 icpc网络赛-Nanjing 题解 L. Magical Girl Haze

版权声明: https://blog.csdn.net/weixin_39778570/article/details/82320836

题目链接:https://nanti.jisuanke.com/t/31001
There are NN cities in the country, and MM directional roads from uu to v(1\le u, v\le n)v(1≤u,v≤n). Every road has a distance c_ic
i
​ . Haze is a Magical Girl that lives in City 11, she can choose no more than KK roads and make their distances become 00. Now she wants to go to City NN, please help her calculate the minimum distance.

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

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

Then the following MM lines each line has three integers, describe a road, U_i, V_i, C_iU
i
​ ,V
i
​ ,C
i
​ . There might be multiple edges between uu and vv.

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

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 南京赛区网络预赛

最短路,然后选出K条之内的路径可变为0,使得1到n最短
于是我们在待定最短路上(也就是即将加入堆的边)进行枚举,假设他就是被设置为0的路,然后加入堆中
放到堆里进行尝试,
这样我们就把一维的dis扩充到二维啦
dis[x][y]表示到1到x点,使用了y次魔法的最短路

#include<bits/stdc++.h>
#define fo(i, j, n) for(int i=j; i<=n; ++i)
#define mk make_pair
#define ll long long
using namespace std;
const int N = 1e5+5;
const int INF = 0x3f3f3f3f;
vector<pair<int, int>> G[N];
struct Node{
    int x,y;
    ll wei;
    Node(){};
    Node(int x, int y, ll wei) : x(x), y(y), wei(wei){}
    bool operator < (const Node &a) const{ return wei>a.wei ;} // 反过来,用最大堆 
}; 
priority_queue<Node> Q;
int n, m, k;
ll dis[N][11];
void read(int &x){
    char ch = getchar();x = 0;
    for (; ch < '0' || ch > '9'; ch = getchar());
    for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
}
void dijkstra(){
    dis[1][0] = 0;
    Q.push(Node(1,0,0));
    int x,y;
    ll wei;
    Node now;
    while(!Q.empty()){
        now = Q.top();
        Q.pop();
        x = now.x;
        y = now.y;
        wei = now.wei;
        //if(dis[x][y] < now.wei) continue; //到x点y次的距离如果已经被更新 这无须执行以下操作
        //if(x==n)break;
        for(auto nxt : G[x]){
            int u = nxt.first;
            int v = nxt.second;
            if(dis[u][y] > wei+v){
                dis[u][y] = wei + v;
                Q.push(Node(u,y,dis[u][y]));
            }
            if(y<k && dis[u][y+1] > wei){
                dis[u][y+1] = wei;
                Q.push(Node(u,y+1,wei));
            }
        } 
    } 
}
int main(){
    int T;scanf("%d",&T);
    while(T--){
        read(n);read(m);read(k);
        fo(i,1,n)G[i].clear();
        int x,y,z;
        fo(i,1,m){
            read(x);read(y);read(z);
            G[x].push_back(mk(y,z));
        }
        if(n==1){
            puts("0");
            break;
        }
        for (int i = 1; i <= n; i++)
            for (int j = 0; j <= k; j++)
                dis[i][j] = 1e18;   
    //  fo(i,1,100)fo(j,1,10)cout<<dis[i][j]<<endl;
        dijkstra();
        ll ans = 1e18;
        fo(i,0,k){
            if(ans>dis[n][i]) ans = dis[n][i];
        }
        printf("%lld\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_39778570/article/details/82320836