2017年8月10号提高组T2 飞行

56 篇文章 0 订阅

Description


有n个城市,编号为0到n-1。小B想从城市s到城市t。他们选择了一家航空公司,这家公司有m种航线,每种航线连接了两个不同的城市。看在小B是个妹子的份上,航空公司的老总给了小B一点优惠:小B可以免费在最多k种航线上搭乘飞机。问小B最小花费是多少。

Input


第一行三个整数n,m,k,分别表示城市数量,航线数量和免费搭乘的航线数量。
第二行两个整数s,t,表示起点和终点。
接下来m行,每行三个整数a.b.c,表示一种航线,即可以从a到b,也可以从b到a,花费为c。

Output


一行一个整数,表示最小花费。

Hint


对于前30%的数据,2<=n<=50,1<=m<=300,k=0;
对于前50%的数据,2<=n<=600,1<=m<=6000,0<=k<=1;
对于前100%的数据,2<=n<=10000,1<=m<=50000,0<=k<=10,c<=1000.

Source


BY BPM

Solution


分层图spfa。dis[i][j]表示i次免费走到j的最小花费

Code


#include <stdio.h>
#include <string.h>
#include <queue>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define erg(i, st) for (int i = ls[st]; i; i = e[i].next)
#define fill(x, t) memset(x, t, sizeof(x))
#define N 10001
#define E 100001
struct edge{int x, y, w, next;}e[E];
bool vis[N][11];
int dis[N][11], ls[N];
int edgeCnt = 0;
std:: queue<int> que;
inline void addEdge(int x, int y, int w){
    e[++ edgeCnt] = (edge){x, y, w, ls[x]}; ls[x] = edgeCnt;
    e[++ edgeCnt] = (edge){y, x, w, ls[y]}; ls[y] = edgeCnt;
}
inline int spfa(int st, int ed, int k){
    while (!que.empty()){que.pop();}
    fill(dis, 31);
    dis[st][0] = 0;
    fill(vis, 0);
    vis[st][0] = 1;
    que.push(st);
    que.push(0);
    while (!que.empty()){
        int now = que.front(); que.pop();
        int stp = que.front(); que.pop();
        erg(i, now){
            if (dis[now][stp] + e[i].w < dis[e[i].y][stp]){
                dis[e[i].y][stp] = dis[now][stp] + e[i].w;
                if (!vis[e[i].y][stp]){
                    que.push(e[i].y);
                    que.push(stp);
                }
            }
            if (dis[now][stp] < dis[e[i].y][stp + 1] && stp < k){
                dis[e[i].y][stp + 1] = dis[now][stp];
                if (!vis[e[i].y][stp + 1]){
                    que.push(e[i].y);
                    que.push(stp + 1);
                }
            }
        }
        vis[now][stp] = 0;
    }
    return dis[ed][k];
}
int main(void){
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);
    int st, ed;
    scanf("%d%d", &st, &ed);
    rep(i, 1, m){
        int x, y, w;
        scanf("%d%d%d", &x, &y, &w);
        addEdge(x, y, w);
    }
    int ans = spfa(st, ed, k);
    printf("%d\n", ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值