123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- Program Dijkstra;
- Const
- Fin = 'input.in';
- Maxn = 10000;
- Type
- Link = ^Node;
- Node = Record
- v, w: Longint; {顶点和费用}
- Next: Link;
- End;
- Var
- Q, {最短路估计值最小堆}
- Q_Pos, {每个顶点在堆中的位置}
- Dist, {最短路估计值}
- Fa: Array[1 .. Maxn]of Longint; {每个顶点的前趋顶点}
- Map: Array[1 .. Maxn]of Link; {用临接表记录的图}
- n, m, s, t, Q_Tot: Longint;
- Procedure Init; {读入}
- Var
- i, a, b, c: Longint;
- p: Link;
- Begin
- Assign(Input, Fin);
- Reset(Input);
- Read(n, m, s, t);
- For i:= 1 to m do
- Begin
- Read(a, b, c);
- {将每条无向边拆成两条有向边插入}
- New(p);
- p^.v:= b; p^.w:= c;
- p^.Next:= Map[a];
- Map[a]:= p;
- New(p);
- p^.v:= a; p^.w:= c;
- p^.Next:= Map[b];
- Map[b]:= p;
- End;
- Close(Input);
- End;
- Procedure Swap(i, j: Longint); {交换堆中的两个元素i,j}
- Var
- k: Longint;
- Begin
- k:= Q[i]; Q[i]:= Q[j]; Q[j]:= k;
- Q_Pos[Q[i]]:= i;
- Q_Pos[Q[j]]:= j;
- End;
- Procedure Updata(i: Longint); {将顶点i上升到合适位置}
- Var
- j: Longint;
- Begin
- j:= i Shr 1;
- While (j >= 1) and (Dist[Q[j]] > Dist[Q[i]]) do
- Begin
- Swap(i, j);
- i:= j; j:= i Shr 1;
- End;
- End;
- Procedure Relax(i, j, w: Longint); {松弛操作}
- Begin
- If w >= Dist[j] Then Exit;
- Dist[j]:= w;
- Fa[j]:= i;
- Updata(Q_Pos[j]);
- End;
- Procedure Heapfy(i: Longint); {将顶点i下降到合适位置}
- Var
- j: Longint;
- Begin
- Repeat
- j:= i;
- {与左儿子比较}
- If (i Shl 1 <= Q_Tot) and (Dist[Q[i Shl 1]] < Dist[Q[i]])
- Then i:= i Shl 1;
- {与右儿子比较}
- If (i Shl 1 < Q_Tot) and (Dist[Q[i Shl 1 + 1]] < Dist[Q[i]])
- Then i:= i Shl 1 + 1;
- If i <> j then Swap(i, j);
- Until (i = j);
- End;
- Procedure Main;
- Var
- i: Longint;
- p: Link;
- Begin
- {最短路估计值初始化}
- For i:= 1 to n do
- Begin
- Q[i]:= i;
- Q_Pos[i]:= i;
- Dist[i]:= $FFFFFF;
- End;
- Swap(1, s); {将源点交换到堆顶}
- Q_Tot:= n; {堆的总元素设为顶点总数n}
- Dist[s]:= 0;
- {Dijkstra算法主过程}
- While Q_Tot > 1 do
- Begin
- i:= Q[1]; {取出堆顶元素}
- {删除取出的元素}
- Swap(1, Q_Tot);
- Dec(Q_Tot);
- Heapfy(1); {维护新堆}
- {对i连出的每条边进行松弛操作}
- p:= Map[i];
- While p <> Nil do
- Begin
- If (Q_Pos[p^.v] <= Q_Tot) then Relax(i, p^.v, Dist[i] + p^.w);
- p:= p^.Next;
- End;
- End;
- End;
- Procedure Print(i: Longint); {递归输出最短路径方案}
- Begin
- If (i = s)
- Then Write(i)
- Else Begin
- Print(Fa[i]);
- Write('--->', i);
- End;
- End;
- Begin
- Init;
- Main;
- If (Dist[t] < $FFFFFF) then
- Begin
- Print(t);
- Writeln;
- Writeln('Total Cost: ', Dist[t]);
- End
- Else
- Writeln('No solution');
- End.
|