优先队列可以用堆实现,用线段树会爆空间,但是我用惯了zkw线段树,不会写二叉堆,于是用可并堆实现了。
const max=1073741819;maxt=500000; var v,tail,tail2:array[1..2000]of longint; f:array[0..2000]of longint; b:array[1..4096]of longint; cost,cost2,sora,sora2,next,next2:array[1..102000]of longint; nt,st,l,r,g,d:array[0..maxt]of longint; m,k,s,t,ss,ss2,tl,m1,n,r1,h:longint; procedure inf; begin assign(input,'2449.in');reset(input); assign(output,'2449.out');rewrite(output) end; procedure ouf; begin close(input);close(output) end; procedure origin; var i:longint; begin m1:=1; while m1<=n+2 do m1:=m1<<1; for i:=1 to n do b[i+m1]:=i; for i:=1 to maxt-1 do nt[i]:=i+1;tl:=maxt; for i:=1 to n do tail[i]:=i;ss:=n; for i:=1 to n do tail2[i]:=i;ss2:=n end; function min(x,y:longint ): longint; begin if d[x]<d[y] then exit(x) else exit(y) end; procedure change(x,w:longint); begin d[x]:=w;x:=(x+m1)>>1; while x<>0 do begin b[x]:=min(b[x<<1],b[x<<1+1]); x:=x>>1 end end; procedure dij(s:longint); var i,x,ne,cos:longint; begin fillchar(d,sizeof(d),127);fillchar(f,sizeof(f),127); change(s,0); while d[b[1]]<max do begin x:=b[1];cos:=d[x];f[x]:=cos;change(x,max); i:=x; while next2[i]<>0 do begin i:=next2[i];ne:=sora2[i]; if d[ne]<>max then if cos+cost2[i]<d[ne] then change(ne,cos+cost2[i]) end end end; procedure ori(x,w:longint); begin st[r1]:=x;g[r1]:=w; l[r1]:=0;r[r1]:=0;d[r1]:=0; r1:=nt[r1] end; procedure del(x:longint); begin st[x]:=0;g[x]:=0; l[x]:=0;r[x]:=0;d[x]:=0; nt[tl]:=x;tl:=x; nt[tl]:=0 end; function merge(x,y:longint ): longint; var e:longint; begin if x=0 then exit(y); if y=0 then exit(x); if g[x]+f[st[x]]>g[y]+f[st[y]] then begin e:=x;x:=y;y:=e end; r[x]:=merge(r[x],y); if d[l[x]]<d[r[x]] then begin e:=l[x];l[x]:=r[x];r[x]:=e end; d[x]:=d[r[x]]+1; exit(x) end; function bfs(s:longint):longint; var x,rr,hh,ne,i,cos:longint; begin fillchar(v,sizeof(v),0); r1:=1;h:=1; ori(s,0); repeat x:=st[h];cos:=g[h];i:=x; inc(v[x]); if (x=t)and(v[x]=k) then exit(cos+f[x]); hh:=h; h:=merge(l[h],r[h]); del(hh); while next[i]<>0 do begin i:=next[i];ne:=sora[i]; if f[ne]<max then begin rr:=r1; ori(ne,cos+cost[i]); h:=merge(h,rr) end end until h=0; exit(-1) end; procedure link(x,y,z:longint); begin inc(ss);next[tail[x]]:=ss;tail[x]:=ss;sora[ss]:=y;cost[ss]:=z; inc(ss2);next2[tail2[y]]:=ss2;tail2[y]:=ss2;sora2[ss2]:=x;cost2[ss2]:=z end; procedure init; var i,x,y,z:longint; begin readln(n,m); origin; for i:=1 to m do begin readln(x,y,z); link(x,y,z) end; readln(s,t,k); if s=t then inc(k); dij(t); if f[s]>max then begin writeln(-1);exit end; fillchar(d,sizeof(d),0); writeln(bfs(s)) end; begin inf; init; ouf end.