Rqnoj341星门跳跃

题目描述

在EVE游戏中,宇宙被划分成为许多区域,每个区域中都有数目不定的星门,可以通过星门来跳跃到特定的区域(星门是双向的)。

现在你正参与BBE联军与MLGBD联盟的会战,但由于飞船受损,需要尽快回到后方的友军空间站进行维护。
试编写程序,计算出所须的最短的返回空间站时间。
为了简化问题,我们约定飞船所在的位置为区域1,空间站所在的位置为区域N。

问题规模:
对于80%的数据,1<N<=10000,1<M<50000;
对于100%的数据,1<N<=30000,1<M<150000,1<=X[],Y[]<=N,1<=Z[]<=4096;

输入格式

第1行,两个整数N,M,分别为区域的总数和星门的总数;
第2..M+1行,每行三个整数X[i],Y[i],Z[i],分别为星门连接的两个区域,以及跳跃所需时间;

输出格式

一个整数,返回空间站所需的最短时间。

====================================================================================

做的时候以为是道模板题,理论上spfa是O(KE)可以A掉的,但貌似我写的栈式Spfa被这个数据卡住了,只好稳妥一点,写个堆优化的dijkstra,O(nlogn+E),瞬间A掉~

====================================================================================

这个Heap-Dijkstra以后可以当模板使~

贴代码:

type hnode=record id,f:longint; end;
     link=^node; node=record x,len:longint; next:link; end;
var heap:array[1..30000] of hnode; size:longint;
    wh:array[1..30000] of longint;
    g:array[1..30000] of link;
    n,m,i,a,b,c:longint;
procedure conn(i,j,dis:longint);
var p:link;
begin
     new(p);
     p^.x:=j;
     p^.len:=dis;
     p^.next:=g[i];
     g[i]:=p;
end;
procedure swap(i,j:longint);
var tmp:hnode;
begin
     tmp:=heap[i];
     heap[i]:=heap[j];
     heap[j]:=tmp;
     wh[heap[i].id]:=i;
     wh[heap[j].id]:=j;
end;
procedure up(i:longint);
var j:longint;
begin
     j:=i shr 1;
     if j>0 then
        if heap[i].f<heap[j].f then begin
           swap(i,j);
           up(j);
        end;
end;
procedure down(i:longint);
var j:longint;
begin
     j:=i shl 1;
     if j<=size then begin
        if j<size then
           if heap[j+1].f<heap[j].f then
              inc(j);
        if heap[j].f<heap[i].f then begin
           swap(i,j);
           down(j);
        end;
     end;
end;
procedure insert(id,f:longint);
begin
     inc(size);
     heap[size].id:=id;
     heap[size].f:=f;
     wh[id]:=size;
     up(size);
end;
procedure pop(var id,dis:longint);
begin
     id:=heap[1].id;
     dis:=heap[1].f;
     swap(1,size);
     dec(size);
     wh[id]:=0;
     down(1);
end;
function dijkstra:longint;
var i,j,x,dis:longint; p:link;
begin
     size:=0;
     insert(1,0);
     for i:=2 to n do insert(i,maxlongint);
     for i:=1 to n do begin
         //for j:=1 to size do write('[',heap[j].id,#32,heap[j].f,']'); writeln;
         pop(x,dis);
         if x=n then exit(dis);
         p:=g[x];
         while p<>nil do begin
               if wh[p^.x]<>0 then
                  if dis+p^.len<heap[wh[p^.x]].f then begin
                     heap[wh[p^.x]].f:=dis+p^.len;
                     up(wh[p^.x]);
                  end;
               p:=p^.next;
         end;
     end;
     exit(maxlongint);
end;
begin
     assign(input,'rq341.in'); reset(input);
     assign(output,'rq341.out'); rewrite(output);
     readln(n,m);
     for i:=1 to m do begin
         readln(a,b,c);
         conn(a,b,c);
         conn(b,a,c);
     end;
     write(dijkstra);
     close(input); close(output);
end.



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值