SSL P2677 飞行fly

来源:互联网 发布:在上海工作的感受 知乎 编辑:程序博客网 时间:2024/05/18 11:27

题目大意:
有n个城市,编号为0到n-1。小B想从城市s到城市t。他选择了一家航空公司,这家公司有m种航线,每种航线连接了两个不同的城市。小B可以免费在最多k种航线上搭乘飞机。问小B最小花费是多少。

对于前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:
这题其实就跟平常的最短路spfa一样,不过多了个限制,所以我们设dis[i,j]表示从s走到第i个点,用了j次免费的机会,最短路是多少。
然后spfa+邻接表去做,做的时候
有2种可以转移:

①dis[t[i],j+1]>dis[s[i],j]
s[i]走到t[i],多用1次免费机会,且比它最优解小。
②dis[t[i],j]>dis[s[i],j]+w[i]
s[i]走到t[i],不用免费机会,走一次花费,且比它最优解小。

时间复杂度:O(2*M+TN)
T远远小于N

var    s,t,w,next:array [0..100001] of longint;    dis:Array [0..10001,0..11] of longint;    list:array [0..10001] of longint;    q:array [0..500001] of longint;    v:array [0..10001] of boolean;    ans,x,y,i,j,n,m,k,p,a1,b1,c1:longint;procedure add(z1,z2,z3,ky:longint);begin    s[ky]:=z1;    t[ky]:=z2;    w[ky]:=z3;    next[ky]:=list[z1];    list[z1]:=ky;end;function min(aa,bb:longint):longint;begin    if aa>bb then exit(bb);    exit(aa);end;procedure spfa;var    i,j,head,tail:longint;begin    head:=0;    tail:=1;    q[1]:=x;    v[x]:=true;    for i:=0 to k do dis[x,i]:=0;    while head<tail do    begin         inc(head);         i:=list[q[head]];         while i>0 do         begin              for j:=0 to k do                if (dis[s[i],j]+w[i]<dis[t[i],j]) or (dis[s[i],j]<dis[t[i],j+1])                   then begin                              dis[t[i],j]:=min(dis[t[i],j],dis[s[i],j]+w[i]);                              dis[t[i],j+1]:=min(dis[t[i],j+1],dis[s[i],j]);                              if not(v[t[i]])                                 then begin                                          inc(tail);                                          q[tail]:=t[i];                                          v[t[i]]:=true;                                      end;                        end;              i:=next[i];         end;         v[q[head]]:=false;    end;end;begin    readln(n,m,k);    readln(x,y);    for i:=1 to m do    begin         readln(a1,b1,c1);         inc(a1); inc(b1);         inc(p); add(a1,b1,c1,p);         inc(p); add(b1,a1,c1,p);    end;    for i:=1 to n do      for j:=0 to k do        dis[i,j]:=maxlongint div 3;    inc(x); inc(y);    spfa;    ans:=maxlongint;    for i:=0 to k do      ans:=min(ans,dis[y,i]);    writeln(ans);end.