bzoj 2763 JLOI 2011 飞行路线 分层图+spfa

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.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值