[Poj]3159——堆优化dijkstra算法

[题目大意]
   抽象一下的话,就是求1到N的最短路
[题解]

   因为点数和边数比较大,我的朴素的SPFA也T了,只好用Heap优化的Dijkstra,效果还是不错的。

[代码]
Poj3159
  1 //10075492      perseawe        3159    Accepted        2880K   563MS   Pascal  2605B   2012-04-15 17:03:44
  2 
  3 Const
  4   MaxNode=30000+300;
  5   MaxEdge=150000+1500;
  6   Inf=1000000000;
  7 
  8 Type
  9   TypeHeap=Record W,Point:Longint;end;//Heap的类型,W是权值,堆的关键字,Point是堆到Dis的映射
 10   TypeEdge=Record c,Wh,next:Longint;end;
 11 
 12 Var
 13   n,m,tot,Src,Sink,ans,Size:Longint;//Size是堆的大小
 14   Heap:Array [0..MaxNode] of TypeHeap;//堆
 15   Edge:Array [0..MaxEdge] of TypeEdge;//边表
 16   Point,Dis,Hv:Array [0..MaxNode] of Longint;//Point是Dis对堆的映射,Dis是最短距离,Hv是查找边表用的
 17 
 18 Procedure AddEdge(u,v,c:Longint);
 19   begin
 20     inc(tot);
 21     Edge[tot].next:=hv[u];hv[u]:=tot;
 22     Edge[tot].wh:=v;Edge[tot].c:=c;
 23   end;
 24 
 25 Procedure Init;
 26   var
 27     i,u,v,c:Longint;
 28   begin
 29     readln(n,m);
 30     tot:=0;Fillchar(hv,sizeof(hv),0);
 31     For i:=1 to m do
 32       begin
 33         readln(u,v,c);
 34         Addedge(u,v,c);
 35       end;
 36   end;
 37 
 38 Procedure SwapHeap(a,b:Longint);//堆中的交换
 39   var
 40     t:Longint;
 41     tmp:TypeHeap;
 42   begin
 43     Point[Heap[a].Point]:=b;Point[Heap[b].Point]:=a;
 44     tmp:=Heap[a];Heap[a]:=Heap[b];Heap[b]:=tmp;
 45   end;
 46 
 47 Procedure PutUp(p:Longint);//堆中的向上调整
 48   begin
 49     while not((p=1)Or(Heap[p shr 1].w<=Heap[p].w)) do
 50       begin
 51         SwapHeap(p,p shr 1);
 52         p:=p shr 1;
 53       end;
 54   end;
 55 
 56 Procedure PutDown(p:Longint);//堆中的向下调整
 57   var
 58     t:Longint;
 59   begin
 60     While Not(p shl 1>Size) do
 61       begin
 62         t:=p shl 1;
 63         if (t<size)and(heap[t].w>heap[t+1].w) then inc(t);
 64         if heap[p].w>heap[t].w then
 65           begin
 66             SwapHeap(p,t);
 67             p:=t;
 68           end
 69         else Break;
 70       end;
 71   end;
 72 
 73 Function GetMin:Longint;//返回最小值的编号
 74   var
 75     Res:Longint;
 76   begin
 77     Res:=Heap[1].Point;
 78     Point[Heap[Size].Point]:=1;
 79     Heap[1]:=Heap[Size];
 80     Dec(Size);
 81     PutDown(1);
 82     Exit(Res);
 83   end;
 84 
 85 Function HeapDij:Longint;
 86   var
 87     I,u,v,tnode:Longint;
 88   begin
 89     For I:=1 to N-1 Do
 90       begin
 91         u:=GetMin;//找一个可选最小,以下是松弛更新部分
 92         tnode:=hv[u];
 93         while tnode<>0 do
 94           begin
 95             v:=Edge[tnode].wh;
 96             if dis[v]>dis[u]+Edge[tnode].c then
 97               begin
 98                 dis[v]:=dis[u]+Edge[tnode].c;
 99                 Heap[Point[v]].W:=dis[v];//调整堆中对应的点
100                 PutUp(Point[v]);//因为值是不断变小的,所以向上调整
101               end;
102             tnode:=Edge[tnode].next;
103           end;
104       end;
105     Exit(Dis[Sink]);
106   end;
107 
108 Procedure BuildHeap;
109   var
110     I:Longint;
111   begin
112     For I:=1 to N do
113       begin
114         Heap[I].W:=Inf;
115         Heap[I].Point:=I;
116         Dis[I]:=Inf;
117         Point[I]:=I;
118       end;
119     Heap[1].W:=0;Dis[1]:=0;
120     Size:=N;
121   end;
122 
123 Procedure Main;
124   begin
125     Src:=1;Sink:=n;
126     BuildHeap;
127     ans:=HeapDij;
128   end;
129 
130 Procedure Print;
131   begin
132     writeln(ans);
133   end;
134 
135 Begin
136   Init;
137   Main;
138   Print;
139 End.

[启发]

  怎么说呢...SPFA可以应对绝大部分的最短路径题目,而且其非常的灵活,代码精炼,但是可惜其理论复杂度是O(VE)的,在稠密图上退化的非常厉害,虽然构造一个是其达到这样上界的数据很麻烦,但是还是可以构造出来的。Heap优化的Dijkstra理论复杂度是O((V+E)logV),在稠密图上表现的非常好,但是代码上劣势太明显了。如果用C++STL里面的优先队列,代码上会好很多,但是效率的下降进队不是一星半点的。(其他人说的,我还不太会CPP,不妄加评论)

posted @ 2012-04-15 17:23  PerSeAwe  阅读(1114)  评论(0编辑  收藏  举报