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

    xiaoxiao2026-01-01  8

    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.
    转载请注明原文地址: https://ju.6miu.com/read-1305550.html
    最新回复(0)