题目描述
A l i c e Alice Alice和 B o b Bob Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在 n n n个城市设有业务,设这些城市分别标记为 0 0 0到 n − 1 n-1 n−1,一共有 m m m种航线,每种航线连接两个城市,并且航线有一定的价格。
A l i c e Alice Alice和 B o b Bob Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多 k k k种航线上搭乘飞机。那么 A l i c e Alice Alice和 B o b Bob Bob这次出行最少花费多少?
输入输出格式
输入格式:
数据的第一行有三个整数,
n
,
m
,
k
n,m,k
n,m,k,分别表示城市数,航线数和免费乘坐次数。
第二行有两个整数,
s
,
t
s,t
s,t,分别表示他们出行的起点城市编号和终点城市编号。
接下来有m行,每行三个整数,
a
,
b
,
c
a,b,c
a,b,c,表示存在一种航线,能从城市
a
a
a到达城市
b
b
b,或从城市
b
b
b到达城市
a
a
a,价格为
c
c
c。
输出格式:
只有一行,包含一个整数,为最少花费。
输入样例#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次机会可以直接通过一条边(也就是免费),问起点与终点之间的最短路径。
一般解决这种问题的时候,我们要将最短路的
d
i
s
dis
dis 数组开成两维。
d
i
s
[
i
]
[
j
]
dis[i][j]
dis[i][j] 表示我走到了
i
i
i号点,使用了
j
j
j次机会的最短路径是多少。
如何更新?
d
i
s
dis
dis数组可以由两个方式更新,对应着两种操作——在这个点我用不用一次机会。
我们设边
E
(
u
,
v
)
E(u , v)
E(u,v)
如果用这次机会
d
i
s
[
v
]
[
j
]
=
d
i
s
[
u
]
[
j
−
1
]
dis[v][j] = dis[u][j-1]
dis[v][j]=dis[u][j−1]
如果不用这次机会
d
i
s
[
v
]
[
j
]
=
d
i
s
[
u
]
[
j
]
+
v
a
l
(
u
,
v
)
dis[v][j] = dis[u][j] + val(u,v)
dis[v][j]=dis[u][j]+val(u,v)
这些操作我们完全可以在SPFA或Dijkstra更新最短路时实现。
还要注意一个坑点 这个题的编号是从 0 0 0 开始的,如果不习惯的话输入时要把编号加上 1 1 1。
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