P4568 [JLOI2011]飞行路线(分层图最短路)

传送门

题目描述:

Alice 和 Bob 现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在n个城市设有业务,设这些城市分别标记为 0到 n1,

一共有 m 种航线,每种航线连接两个城市,并且航线有一定的价格。Alice 和 Bob 现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。

航空公司对他们这次旅行也推出优惠,他们可以免费在最多 k 种航线上搭乘飞机。那么 Alice 和 Bob 这次出行最少花费多少?

思路:分层图,把图分为k+1层,每上一层的边的起点对下一层的相同边的终点连一条权值为0的边,表示可以免费乘坐,

从上一层到下一层只会选择一条权值为0的边,所以再跑最短路就能选择出k条边来免费通过。

注意k>m的情况,我们需要把每一层的终点对下一层终点连权值为0的边,这样就能在之前就到达终点然后直接走到

最后一层的终点,或者就直接把k取min(k,m);

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 10000005;
struct edge {
    int f, t,w,nxt;
}e[maxn*2];
int hd[maxn], tot;
void add(int f, int t,int w) {
    e[++tot] = { f,t,w,hd[f] };
    hd[f] = tot;
}
int dis[maxn];
bool vis[maxn];
struct node {
    int dis,id;
    bool operator<(node b)const {
        return dis > b.dis;
    }
};
int dj(int s,int t) {
    memset(dis, 0x3f, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    priority_queue<node>q;
    dis[s] = 0;
    q.push({ 0,s });
    while (!q.empty()) {
        node t = q.top(); q.pop();
        if (vis[t.id])continue;
        vis[t.id] = 1;
        int u = t.id;
        for (int i = hd[u]; i; i = e[i].nxt) {
            int v = e[i].t;
            if (vis[v])continue;
            if (dis[u] + e[i].w < dis[v]) {
                dis[v] = dis[u] + e[i].w;
                q.push({ dis[v], v });
            }
        }
    }
    return dis[t];
}
int n, m, k;
int s, t;
int main() {
    //freopen("test.txt", "r", stdin);
    scanf("%d%d%d", &n, &m, &k);
    k = min(m, k);
    scanf("%d%d", &s, &t);    
    for (int i = 1; i <= m; i++) {
        int a, b,w; scanf("%d%d%d", &a, &b, &w);
        for (int j = 0; j <= k; j++) {
            add(j * n + a, j * n + b, w);
            add(j * n + b, j * n + a, w);
            if (j != 0) {
                //上一层与下一层连边
                add((j - 1) * n + a, j * n + b, 0);
                add((j - 1) * n + b, j * n + a, 0);
            }
        }
    }
    printf("%d",dj(s, k * n + t));
    return 0;
}

 

posted @ 2021-04-16 18:54  cono奇犽哒  阅读(61)  评论(0)    收藏  举报