2017年8月10号提高组T2 飞行

Description

有n个城市,编号为0到n-1。小B想从城市s到城市t。他们选择了一家航空公司,这家公司有m种航线,每种航线连接了两个不同的城市。看在小B是个妹子的份上,航空公司的老总给了小B一点优惠:小B可以免费在最多k种航线上搭乘飞机。问小B最小花费是多少。

Input

第一行三个整数n,m,k,分别表示城市数量,航线数量和免费搭乘的航线数量。
第二行两个整数s,t,表示起点和终点。
接下来m行,每行三个整数a.b.c,表示一种航线,即可以从a到b,也可以从b到a,花费为c。

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,c<=1000.

分析:
在spfa的距离d[i]加一维为d[i,j]为走到i,用了j次免费的答案。

代码:

const
  MaxE=50002;
  MaxV=100001*2;

type
  rec=record
   x,y,w,next:longint;
  end;
var
  n,m,c,i,x,y,w,o,ed,k,l:longint;
  g:array [-1..Maxv] of rec;
  ls:array [-1..Maxe] of longint;
  v,list:array [-1..maxe] of longint;
  d:array [-1..maxe,-1..10] of longint;

procedure spfa(first:longint;k:longint);
var
  head,tail,t,i:longint;
begin
  tail:=1; head:=0;
  list[1]:=first;
  for i:=1 to n do
  d[i,k]:=maxlongint;
  d[first,k]:=0;
  v[first]:=1;
  while tail<>head do
    begin
      head:=head mod maxe+1;
      t:=ls[list[head]];
      while t>0 do
        with g[t] do
          begin
            if d[x,k]+w<d[y,k] then
              begin
                d[y,k]:=d[x,k]+w;
                if v[y]=0 then
                  begin
                    v[y]:=1;
                    tail:=tail mod maxe+1;
                    list[tail]:=y;
                  end;
              end;
            if (d[x,k-1]<d[y,k]) and (k<>0) then
              begin
                d[y,k]:=d[x,k-1];
                if v[y]=0 then
                  begin
                    v[y]:=1;
                    tail:=tail mod maxe+1;
                    list[tail]:=y;
                  end;
              end;
            t:=next;
          end;
      v[list[head]]:=0;
    end;
end;

procedure add(x,y,w:longint);
 begin
  inc(o);
  g[o].x:=x;
  g[o].y:=y;
  g[o].w:=w;
  g[o].next:=ls[x];
  ls[x]:=o;
 end;

begin
 assign(input,'fly.in');
 assign(output,'fly.out');
 reset(input);
 rewrite(output);
 read(n,m,k);
 read(c,ed);
 for i:=1 to m do
  begin
   read(x,y,w);
   add(x,y,w);
   add(y,x,w);
  end;
 for l:=0 to k do
  spfa(c,l);
 writeln(d[ed,k]);
 close(input);
 close(output);
end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值