[Poj]3159——堆优化dijkstra算法
[题目大意]
抽象一下的话,就是求1到N的最短路
[题解]
抽象一下的话,就是求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.
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,不妄加评论)
——————————————————————————————————————
你说,我们的存在,永不消逝。对吧?
如果,我们都在努力创造了存在。我们,会幸福的。对吧?