Description
Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格。Alice和Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多k种航线上搭乘飞机。那么Alice和Bob这次出行最少花费多少?
Input
数据的第一行有三个整数,n,m,k,分别表示城市数,航线数和免费乘坐次数。
第二行有两个整数,s,t,分别表示他们出行的起点城市编号和终点城市编号。
接下来有m行,每行三个整数,a,b,c,表示存在一种航线,能从城市a到达城市b,或从城市b到达城市a,价格为c。(0<=a,b<=n,a与b不相等,0<=c<=1000)
Output
只有一行,包含一个整数,为最少花费。
分析
一个分层图。
设f[i,j]为到达i点用了j次免费的最短路。
ps:要把spfa的队列开大一些(8000000+)或者打循环队列。
代码
const
maxn=20000;
maxe=400000;
type
arr=record
x,y:longint;
w:longint;
next:longint;
end;
var
n,m,nm,num:longint;
s,t:longint;
edge:array[0..maxe] of arr;
ls:array[0..maxn] of longint;
f:array[0..maxn,0..100] of longint;
queue:array[0..maxe*20,1..2] of longint;
status:array[0..maxn,0..100] of longint;
procedure add(x,y,w:longint);
begin
num:=num+1;
edge[num].x:=x;
edge[num].y:=y;
edge[num].w:=w;
edge[num].next:=ls[x];
ls[x]:=num;
num:=num+1;
edge[num].x:=y;
edge[num].y:=x;
edge[num].w:=w;
edge[num].next:=ls[y];
ls[y]:=num;
end;
procedure init;
var
i:longint;
x,y,w:longint;
begin
readln(n,m,nm);
readln(s,t);
num:=0;
for i:=1 to m do
begin
readln(x,y,w);
add(x,y,w);
end;
end;
procedure spfa;
var
i,j,k:longint;
head,tail:longint;
begin
fillchar(f,sizeof(f),$7f);
head:=0; tail:=1;
queue[1][1]:=s;
queue[1][2]:=0;
f[s][0]:=0;
status[s][0]:=1;
repeat
head:=head+1;
i:=ls[queue[head][1]];
while i<>0 do
begin
with edge[i] do
begin
j:=queue[head][2];
if f[x,j]+w<f[y,j]
then
begin
f[y,j]:=f[x,j]+w;
if status[y][j]=0
then
begin
tail:=tail+1;
queue[tail][1]:=y;
queue[tail][2]:=j;
status[y][j]:=1;
end;
end;
if j<nm then
if f[x,j]<f[y,j+1]
then
begin
f[y,j+1]:=f[x,j];
if status[y][j+1]=0
then
begin
tail:=tail+1;
queue[tail][1]:=y;
queue[tail][2]:=j+1;
status[y][j+1]:=1;
end;
end;
i:=next;
end;
end;
status[queue[head][1]][queue[head][2]]:=0;
until head=tail;
end;
procedure main;
var
i,j,k:longint;
ans:longint;
begin
spfa;
ans:=maxlongint;
for i:=0 to nm do
begin
if ans>f[t,i] then ans:=f[t,i];
end;
writeln(ans);
end;
begin
init;
main;
end.