本来很早以前就用线段树写了一遍,但是居然mle了。。。
先用dij求各点到汇点的最短路f[i],再从源点bfs A*搜,g[j]:=g[i]+c[i,j];g表示到源点距离,每次扩展都选g[i]+f[i]最小的点,向其他点扩展一种状态而不是点,所以优先队列中的点可能超过n。
先用dij求各点到汇点的最短路f[i],再从源点bfs A*搜,g[j]:=g[i]+c[i,j];g表示到源点距离,每次扩展都选g[i]+f[i]最小的点,向其他点扩展一种状态而不是点,所以优先队列中的点可能超过n。
优先队列可以用堆实现,用线段树会爆空间,但是我用惯了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.