L. Magical Girl Haze(ACM-ICPC 2018 Nanjing Area Network Preliminary Competition, Layered Shortest Path, Heap Optimized dijkstra)

Keywords: network Programming

describe

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_ici. 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_iUi,Vi,Ci. 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≤Ci≤1e9. There is at least one path between City 11 and City NN.

Output

For each test case, print the minimum distance.

sample input

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

sample output

3

Source of title

ACM-ICPC 2018 Nanjing Area Network Preliminary Competition

thinking

Given a directed graph with mm edges of nn points, from 11 points to nn points, there is a kk chance to make the cost of one edge change to 00, and the minimum cost from 11 to nn is obtained.

Subject meaning and sum BZOJ2763 flight route (layered shortest path, dijkstra heap optimization) It's exactly the same. It's the shortest path in layers.

We need to use ideas like dynamic programming to transfer.

We define:

  • dis[i][j]dis[i][j]: From the starting point st to point i, the minimum cost of using J preferential opportunities is used.
  • vis[i][j]vis[i][j]: from point st to point i, is the status of using J preferential opportunities marked?

We need to make some changes to the ordinary Dijstra transfer:

  1. When free opportunities are not used:

    If the cost of arrival u is dis[u][k] + the edge weight W < to the edge weight dis[v][k] from u to V
     Normal metastasis update: dis[v][k]=dis[u][k]+w
     Add heap q.push(node(v,k,dis[v][k])
  2. When using free opportunities:

    If the cost of K opportunities is dis [u] [k] < the edge weight dis[v][k+1] of k+1 opportunities is used at point u
     This side is free to update dis[v][k+1]=dis[u][k]
    Add heap q.push(node(v,k+1,dis[v+1][k])

All that's left is Diegerstella's heap optimization template.

Code

#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
const int inf = 0x3f3f3f3f;
const int N = 1e5 + 10;
int first[N], tot;
int n, m, k;
struct edge
{
    int v, w, next;
} e[N * 2];
void add_edge(int u, int v, int w)
{
    e[tot].v = v, e[tot].w = w;
    e[tot].next = first[u];
    first[u] = tot++;
}
void init()
{
    mem(first, -1);
    tot = 0;
}
struct node
{
    int id, k, now;
    node() {}
    node(int _id, int _k, int _now)
    {
        id = _id, k = _k, now = _now;
    }
    bool friend operator<(node a, node b)
    {
        return a.now > b.now;
    }
};
int dis[N][12], vis[N][12];
void dijkstra(int st)
{
    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j <= k; j++)
        {
            dis[i][j] = inf;
            vis[i][j] = 0;
        }
    }
    dis[st][0] = 0;
    priority_queue<node> q;
    q.push(node(st, 0, 0));
    while (!q.empty())
    {
        node u = q.top();
        q.pop();
        if (!vis[u.id][u.k])
        {
            vis[u.id][u.k] = 1;
            for (int i = first[u.id]; ~i; i = e[i].next)
            {
                int v = e[i].v, w = e[i].w;
                if (!vis[v][u.k] && dis[u.id][u.k] + w < dis[v][u.k])
                {
                    dis[v][u.k] = dis[u.id][u.k] + w;
                    q.push(node(v, u.k, dis[v][u.k]));
                }
                if (u.k < k && !vis[v][u.k] && dis[u.id][u.k] < dis[v][u.k + 1])
                {
                    dis[v][u.k + 1] = dis[u.id][u.k];
                    q.push(node(v, u.k + 1, dis[v][u.k + 1]));
                }
            }
        }
    }
}
void solve()
{
    int u, v, w;
    scanf("%d%d%d", &n, &m, &k);
    init();
    for (int i = 1; i <= m; i++)
    {
        scanf("%d%d%d", &u, &v, &w);
        add_edge(u, v, w);
    }
    dijkstra(1);
    int ans = inf;
    for (int i = 0; i <= k; i++)
        ans = min(ans, dis[n][i]);
    printf("%d\n", ans);
}
int main()
{
    //freopen("in.txt", "r", stdin);
    int t;
    scanf("%d", &t);
    while (t--)
        solve();
    return 0;
}

Posted by webrajesh on Sun, 03 Feb 2019 20:24:16 -0800