Description
(Alice) 和 (Bob) 现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在 (n) 个城市设有业务,设这些城市分别标记为 (0) 到 (n-1),一共有 (m) 种航线,每种航线连接两个城市,并且航线有一定的价格。 (Alice) 和 (Bob) 现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多k种航线上搭乘飞机。那么 (Alice) 和 (Bob) 这次出行最少花费多少?
Input
数据的第一行有三个整数, (n,m,k) ,分别表示城市数,航线数和免费乘坐次数。
第二行有两个整数, (s,t) ,分别表示他们出行的起点城市编号和终点城市编号。 ((0le s,t<n))
接下来有 (m) 行,每行三个整数, (a,b,c) ,表示存在一种航线,能从城市 (a) 到达城市 (b) ,或从城市 (b) 到达城市 (a) ,价格为 (c) 。( (0le a,b<n,a) 与 (b) 不相等, (0le cle 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
对于 (100\%) 的数据, (2le nle 10000,1le mle 50000,0le kle 10) .
Solution
分层图最短路裸题,用优先队列去除后效性,可用于套版。
#include<bits/stdc++.h>
using namespace std;
#define N 100001
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define fech(i, x) for (int i = 0; i < x.size(); i++)
#define ll long long
inline int read() {
int x = 0, flag = 1; char ch = getchar(); while (!isdigit(ch)) { if (!(ch ^ '-')) flag = -1; ch = getchar(); }
while (isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); return x * flag;
}
int n, m, k, S, T;
struct edge { int u, v, w; } eg[N]; int tot;
vector<int> g[N];
int d[N][11];
bool vis[N][11];
struct node {
int u, d, f;
bool operator < (const node& b) const { return d > b.d; }
};
priority_queue<node> q;
void bfs() {
memset(d, 127, sizeof d); d[S][0] = 0;
q.push(node { S, 0, 0 });
while(!q.empty()) {
node x = q.top(); q.pop();
int u = x.u, dis = x.d, f = x.f;
if(!(u ^ T)) { cout << dis; exit(0); }
if(vis[u][f]) continue;
vis[u][f] = 1;
fech(i, g[u]) {
edge e = eg[g[u][i]];
if(f < k && !vis[e.v][f + 1] && d[e.v][f + 1] > dis) d[e.v][f + 1] = dis, q.push(node{ e.v, dis, f + 1 });
if(!vis[e.v][f] && d[e.v][f] > dis + e.w) d[e.v][f] = dis + e.w, q.push(node{ e.v, dis + e.w, f });
}
}
}
int main() {
scanf("%d%d%d%d%d", &n, &m, &k, &S, &T);
while(m--) {
int u = read(), v = read(), w = read();
eg[++tot] = edge { u, v, w }; g[u].push_back(tot);
eg[++tot] = edge { v, u, w }; g[v].push_back(tot);
}
bfs();
}