BZOJ 2763: [JLOI2011]飞行路线

Description

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

Input

数据的第一行有三个整数,n,m,k,分别表示城市数,航线数和免费乘坐次数。

第二行有两个整数,s,t,分别表示他们出行的起点城市编号和终点城市编号。(0<=s,t<n)

接下来有m行,每行三个整数,a,b,c,表示存在一种航线,能从城市a到达城市b,或从城市b到达城市a,价格为c。(0<=a,b<n,a与b不相等,0<=c<=1000)

Output

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

Sample Input

5 6 1

0 4

0 1 5

1 2 5

2 3 5

3 4 5

2 3 3

0 2 100

Sample Output

8

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.

Solution

很有意思的题目。我们把图复制k成层,第i层表示用了i次优惠券了。那么在相邻层之间的相邻接点连一条权值为0的单向边,跑一遍最短路,答案就是所有层中T的距离最小值。

然后这道题因为初始化把S到T的dis设为INF,所以WA了几次QAQ…大家一定要吸取我的教训呀!

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <functional>
#include <queue>
#include <map>
using namespace std;
typedef long long LL;
const int INF = 1<<30;
int getint() {
    int r = 0, k = 1; char c = getchar();
    for (; '0' > c || c > '9'; c = getchar()) if (c == '-') k = -1;
    for (; '0' <= c && c <= '9'; c = getchar()) r = r * 10 - '0' + c;
    return r * k;
}
int n, m, k;
int id[20005][15];
int dis[300005];
typedef pair<int, int> pii;
int tot = 0;
priority_queue<pii, vector<pii>, greater<pii> > Q;
struct MagHSK {
    int to, next, w;
} edge[5000005];
int cnte = 1, S, T, h[300005];
bool vis[300005];
void ins(int x, int y, int z) {
    edge[++cnte].to = y;
    edge[cnte].next = h[x];
    edge[cnte].w = z;
    h[x] = cnte;
}
pii tmp;
int dijkstra() {
    int now, ndis;
    Q.push(make_pair(0, S));
    for (int i = 0; i <= tot; ++i) dis[i] = INF; dis[S] = 0;
    while (!Q.empty()) {
        tmp = Q.top();
        Q.pop();
        ndis = tmp.first; now = tmp.second;
        if (vis[now]) continue;
        vis[now] = true;
        for (int i = h[now]; i; i = edge[i].next) {
            if (vis[edge[i].to]) continue;
            if (dis[edge[i].to] > ndis + edge[i].w) {
                dis[edge[i].to] = ndis + edge[i].w;
                Q.push(make_pair(dis[edge[i].to], edge[i].to));
            }
        }
    }
    int ret = INF;
    for (int i = 0; i <= k; ++i) ret = min(ret, dis[id[T][i]]);
    return ret;
}
int main() {
    n = getint(); m = getint(); k = getint();
    for (int i = 0; i <= k; ++i)
        for (int j = 1; j <= n; ++j)
            id[j][i] = ++tot;
    S = getint() + 1; T = getint() + 1;
    S = id[S][0];
    int x, y, z;
    for (int i = 1; i <= m; ++i) {
        x = getint() + 1; y = getint() + 1; z = getint();
        for (int j = 0; j < k; ++j) {
            ins(id[x][j], id[y][j], z);
            ins(id[y][j], id[x][j], z);
            ins(id[x][j], id[y][j+1], 0);
            ins(id[y][j], id[x][j+1], 0);
        }
        ins(id[x][k], id[y][k], z);
        ins(id[y][k], id[x][k], z);
    }
    int ans = dijkstra();
    printf("%d", ans);
    return 0;
}