[JLOI2011]飞行路线

题目描述

Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在 nnn 个城市设有业务,设这些城市分别标记为 000 到 n−1n-1n1 ,一共有 mmm 种航线,每种航线连接两个城市,并且航线有一定的价格。

Alice和Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多 kkk 种航线上搭乘飞机。那么Alice和Bob这次出行最少花费多少?

输入输出格式

输入格式:

数据的第一行有三个整数, n,m,kn,m,kn,m,k ,分别表示城市数,航线数和免费乘坐次数。
第二行有两个整数, s,ts,ts,t ,分别表示他们出行的起点城市编号和终点城市编号。
接下来有m行,每行三个整数, a,b,ca,b,ca,b,c ,表示存在一种航线,能从城市 aaa 到达城市 bbb ,或从城市 bbb 到达城市 aaa ,价格为 ccc 。

输出格式:

只有一行,包含一个整数,为最少花费。

输入输出样例

输入样例#1: 
5 6 1
0 4
0 1 5
1 2 5
2 3 5
3 4 5
2 3 3
0 2 100
输出样例#1: 
8

说明

对于30%的数据, 2≤n≤50,1≤m≤300,k=02 \le n \le 50,1 \le m \le 300,k=02n50,1m300,k=0 ;
对于50%的数据, 2≤n≤600,1≤m≤6000,0≤k≤12 \le n \le 600,1 \le m \le 6000,0 \le k \le 12n600,1m6000,0k1 ;
对于100%的数据, 2≤n≤10000,1≤m≤50000,0≤k≤102 \le n \le 10000,1 \le m \le 50000,0 \le k \le 102n10000,1m50000,0k10 , 0≤s,t<n,0≤a,b<n,a≠b,0≤c≤10000 \le s,t<n,0 \le a,b<n,a\neq b,0 \le c \le 10000s,t<n,0a,b<n,ab,0c1000

 


 

分层最短路, 设dis[i][j]表示到第i个点, 用了j次免费的边的最短路。

然后对于扩展到的每一个节点都有两种方案, 一是不把这条边当成免费边, 二是把这条边当做免费边;

于是就类似一个动态规划, 数据卡spfa, 但加了slf优化就过了。

 


 

// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int N = 10005, M = 100005;
int n, m, k;
int s, t;
struct edge{
    int nxt, to, val;
}ed[M];
int head[N], cnt;
inline void add(int x, int y, int z)
{
    ed[++cnt] = (edge){head[x], y, z};
    head[x] = cnt;
}
int dis[N][105];
bool ex[N][105];
struct date{
    int x, val, stp;
    friend bool operator < (date a, date b)
    {
        return a.val > b.val;
    }
};

inline void spfa()
{
    priority_queue <date> q;
    q.push((date){s, 0, 0});
    memset(dis, 0x3f, sizeof dis);
    ex[s][0] = 1;
    dis[s][0] = 0;
    while(!q.empty())
    {
        int x = q.top().x, tp = q.top().stp;
        ex[x][tp] = 0;
        q.pop();
        for (int i = head[x] ; i ; i = ed[i].nxt)
        {
            int to = ed[i].to;
            if (dis[to][tp] > dis[x][tp] + ed[i].val)
            {
                dis[to][tp] = dis[x][tp] + ed[i].val;
                if (!ex[to][tp])
                {
                    ex[to][tp] = 1;
                    q.push((date){to, dis[to][tp], tp});
                }
            }
        }
        if (tp + 1 <= k)
        {
            for (int i = head[x] ; i ; i = ed[i].nxt)
            {
                int to = ed[i].to;
                if (dis[to][tp+1] > dis[x][tp])
                {
                    dis[to][tp+1] = dis[x][tp];
                    if (!ex[to][tp+1])
                    {
                        ex[to][tp+1] = 1; 
                        q.push((date){to,dis[to][tp+1], tp+1});
                    }
                }
            }
        }
    }
}

int main()
{
    scanf("%d%d%d", &n, &m, &k);
    scanf("%d%d", &s, &t); 
    for (int i = 1 ; i <= m ; i ++)
    {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        add(x, y, z), add(y, x, z);
    }
    spfa();
    printf("%d\n", dis[t][k]);
    return 0; 
}

 

 

 

posted @ 2018-07-19 22:55  zZhBr  阅读(320)  评论(0编辑  收藏  举报