飞行路线 题解

原题点这里

题目描述

Alice 和 Bob 现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在 (n) 个城市设有业务,设这些城市分别标记为 (0)(n−1),一共有 (m) 种航线,每种航线连接两个城市,并且航线有一定的价格。
Alice 和 Bob 现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多 (k) 种航线上搭乘飞机。那么 Alice 和 Bob 这次出行最少花费多少?

  • 输入格式 第一行三个整数 (n,m,k) 分别表示城市数,航线数和免费乘坐次数。
    接下来一行两个整数 (s,t),分别表示他们出行的起点城市编号和终点城市编号。
    接下来 (m) 行,每行三个整数 (a,b,c),表示存在一种航线,能从城市 (a) 到达城市 (b),或从城市 (b) 到达城市 (a),价格为 (c)

  • 输出格式 输出一行一个整数,为最少花费。

样例输入

5 6 1
0 4
0 1 5
1 2 5
2 3 5
3 4 5
2 3 3
0 2 100

样例输入

8

分析

分层图。。。
各层内部正常连边,各层之间从上到下连权值为0的边。每向下跑一层,就相当于免费搭一次飞机。跑一遍从 (s)(t+n∗k) 的最短路即可。

AC代码

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
struct edge {
    int to, next, weight;
} a[6000060];
struct node {
    int dist, id;
    node() {}
    node(int dist, int id) : dist(dist), id(id) {}
};
bool operator<(node xi, node yi) { return xi.dist > yi.dist; }
int n, m, k;
int s, t;
int x, y, w;
int cnt(0);
int head[1000010];
int vis[1000010];
int dist[1000010];
void addedge(int xi, int yi, int wi) {
    a[cnt].to = yi;
    a[cnt].next = head[xi];
    a[cnt].weight = wi;
    head[xi] = cnt++;
}
void dijkstra(int s) {
    memset(vis, 0, sizeof(vis));
    memset(dist, INF, sizeof(dist));
    priority_queue<node> q;
    q.push(node(0, s));
    dist[s] = 0;
    while (!q.empty()) {
        node t(q.top());
        q.pop();
        if (vis[t.id])
            continue;
        vis[t.id] = 1;
        for (int i = head[t.id]; i != -1; i = a[i].next) {
            int v = a[i].to;
            if (dist[v] > a[i].weight + t.dist) {
                dist[v] = a[i].weight + t.dist;
                q.push(node(dist[v], v));
            }
        }
    }
}
int main() {
    memset(head, -1, sizeof(head));
    scanf("%d%d%d", &n, &m, &k);
    scanf("%d%d", &s, &t);
    for (int i = 1; i <= m; i++) {
        scanf("%d%d%d", &x, &y, &w);
        addedge(x, y, w);
        addedge(y, x, w);
        for (int j = 1; j <= k; j++) {
            addedge(x + (j * n), y + (j * n), w);
            addedge(y + (j * n), x + (j * n), w);
            addedge(x + ((j - 1) * n), y + (j * n), 0);
            addedge(y + ((j - 1) * n), x + (j * n), 0);
        }
    }
    for (int i = 1; i <= k; i++) addedge(t + (i - 1) * n, t + i * n, 0);
    dijkstra(s);
    printf("%d", dist[t + k * n]);
    return 0;
}
原文地址:https://www.cnblogs.com/Chain-Forward-Star/p/13868095.html