都说裸迪杰斯特拉太慢,+heap又太长。
于是我发明了迪杰斯特拉+线段树
根据线段树支持区间修改性质,也许有图可以卡堆但可以用线段树做,还在研究ing
先贴代码
用poj1797测速 235ms是pascal中速度最快的
const max=2139062144; //取这个值是为了判节点取过没有 var n,m,m1,s,t,ss:longint; tail,sora,next,cost,d,b:array[0..100000]of longint; function min(x,y:longint):longint; //不可用maths库 因为线段树中存的是节点序号 begin if d[b[x]]<d[b[y]] then exit(b[x]) else exit(b[y]) end; procedure change(x,y:longint); //修改线段树 begin d[x]:=y;inc(x,m1);x:=x>>1; while x<>0 do begin b[x]:=min(x<<1,x<<1+1);x:=x>>1 end;//还可以优化速度,不过为了拼行数 没加优化 end; procedure origin; begin s:=1;t:=n;ss:=t;fillchar(d,sizeof(d),127); for m1:=s to t do tail[m1]:=m1; m1:=1;while m1<=n do m1:=m1<<1;dec(m1); //计算叶子 for t:=1 to t do b[t+m1]:=t //线段树初始化 end; procedure link(x,y,z:longint); //邻接表 begin inc(ss);next[tail[x]]:=ss;sora[ss]:=y;cost[ss]:=z;tail[x]:=ss; inc(ss);next[tail[y]]:=ss;sora[ss]:=x;cost[ss]:=z;tail[y]:=ss end; procedure init; var i,x,y,z,ne,cos:longint; begin readln(n,m);origin; for i:=1 to m do begin readln(x,y,z);link(x,y,z) end; // 输入连边 x:=s;d[s]:=0; while x<>t do begin i:=x;cos:=d[x];change(x,maxlongint); //维护 while next[i]<>0 do begin i:=next[i];ne:=sora[i]; if (d[ne]<max)and(cos+cost[i]<d[ne]) then change(ne,cos+cost[i]) //修改 end; x:=b[1] //取距离最近点 end; writeln(d[t]) end; begin init end. //做的是无向图,还没测过速,不过只有43行(+heap有70+行)理论复杂度是 修改o(log n);取最小节点 o(1) 但维护又要o(log n)。 //实际运行上常数可能会比+heap大。加了优化可能会更快。