题目描述
AliceAliceAlice和BobBobBob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在nnn个城市设有业务,设这些城市分别标记为000到n−1n-1n−1,一共有mmm种航线,每种航线连接两个城市,并且航线有一定的价格。
AliceAliceAlice和BobBobBob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多kkk种航线上搭乘飞机。那么AliceAliceAlice和BobBobBob这次出行最少花费多少?
输入输出格式
输入格式:
数据的第一行有三个整数,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
关于分层图最短路
(以下来自度娘)
分层图最短路是指在可以进行分层图的图上解决最短路问题。
一般模型是:
在图上,有k次机会可以直接通过一条边(也就是免费),问起点与终点之间的最短路径。
一般解决这种问题的时候,我们要将最短路的disdisdis 数组开成两维。
dis[i][j]dis[i][j]dis[i][j] 表示我走到了iii号点,使用了jjj次机会的最短路径是多少。
如何更新?
disdisdis数组可以由两个方式更新,对应着两种操作——在这个点我用不用一次机会。
我们设边 E(u,v)E(u , v)E(u,v)
如果用这次机会 dis[v][j]=dis[u][j−1]dis[v][j] = dis[u][j-1]dis[v][j]=dis[u][j−1]
如果不用这次机会dis[v][j]=dis[u][j]+val(u,v)dis[v][j] = dis[u][j] + val(u,v)dis[v][j]=dis[u][j]+val(u,v)
这些操作我们完全可以在SPFA或Dijkstra更新最短路时实现。
还要注意一个坑点 这个题的编号是从000 开始的,如果不习惯的话输入时要把编号加上111。
code
#include<bits/stdc++.h>
using namespace std;
const int maxn = 10005, maxm = 100005;
struct node
{
int f, t, v;
}e[maxm];
int n, m, tot, k, S, T, ans = 1e9;
int head[maxn], nxt[maxm], used[maxn] , dis[maxn][12];
#define ri register int
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
return x * f;
}
inline void buildnode(int a, int b, int c)
{
tot++;
e[tot].f = a;
e[tot].t = b;
e[tot].v = c;
nxt[tot] = head[a];
head[a] = tot;
}
typedef pair<int, int>p;
struct cmp
{
bool operator()(p a, p b)
{
return a.first > b.first;
}
};
priority_queue<p, vector<p>, cmp>q;
inline void dijkstra(int s)
{
for (ri i = 1; i <= n; i++)
for (ri j = 0; j <= 10; j++) dis[i][j] = 1e9;
dis[s][0] = 0;
q.push(p(dis[s][0], s));
while (!q.empty())
{
p x = q.top();
q.pop();
int flag = 0;
for (ri i = head[x.second]; i; i = nxt[i])
{
int u = e[i].t;
for(ri j = 0 ; j <= k ; j ++)
if (dis[u][j] > dis[x.second][j] + e[i].v)
{
dis[u][j] = dis[x.second][j] + e[i].v;
q.push(p(dis[u][j], u));
flag = 1;
}
for (ri j = 1; j <= k; j++)
{
if (dis[u][j] > dis[x.second][j - 1])
dis[u][j] = dis[x.second][j - 1], flag = 1;
}
if (flag == 1) q.push(p(dis[u][0], u));
}
}
}
int main()
{
n = read(); m = read(); k = read();
S = read(); T = read();
S += 1; T += 1;
for (ri i = 1; i <= m; i++)
{
int a, b, c;
a = read(); b = read(); c = read();
a += 1, b += 1;
buildnode(a, b, c);
buildnode(b, a, c);
}
dijkstra(S);
for (ri i = 0; i <= k; i++) ans = min(ans, dis[T][i]);
printf("%d", ans);
//system("pause");
}
End