Theme portal
Bessie has two fragrant and crisp red apples for her two friends. Of course, the C (1 <= C <= 200000) cattle paths that she can walk are included in a commonly used graph, which contains P (1 <= P <= 100000) pastures, marked as 1. P. There is no "bull road" that goes back to itself from a ranch. The "bull road" is bidirectional, and each bull road is marked with a distance. Most importantly, each pasture leads to another pasture. Each bull road connects two different pastures P1_i and P 2_i (1<=P1_i, P2_i<=P), and the distance is D_i. The total distance of all "bull roads" is not greater than 2000000000.
Now Bessie is going to send an apple to the PA_1 and PA_2 ranches from the PB ranch (the order of PA_1 and PA_2 can be changed), so what's the shortest distance? Of course, PB, PA_1 and PA_2 are different.
Input and Output Format
Input format:
-
Line 1: Line 1 contains five space-separated integers: C, P, PB, PA1, and PA2
-
Lines 2…C+1: Line i+1 describes cowpath i by naming two pastures it connects and the distance between them: P1_i, P2_i, D_i
Output format:
- Line 1: The shortest distance Bessie must travel to deliver both apples
sample input
9 7 5 1 4
5 1 7
6 7 2
4 7 2
5 6 1
5 2 4
4 3 2
1 2 3
3 2 2
2 6 3
sample output
12
This question is the naked shortest path.
Bessie has only two ways of walking: Pb - > PA1 - > pa2 or Pb - > pa2 - > PA1
So we just need to figure out the shortest path from each point to pa1 and pa2.
But, the data range is a little big. As a pascal player, I am not bothered to do a lot of excellent dij. Write SPFA. SPFA is too unstable, so I think of an optimized version of SPFA I've seen.
Namely, if the shortest path from the point at the end of the team to the point at the source is less than that at the head of the team, it is added to the head of the team.
Implement code (where u is the newly added node):
if dis[u] < dis[q[h + 1]] then swap(q[t], q[h + 1]);
Well, I added this sentence to optimize a lot of time, but spfa is still too empty in the examination room, I dare not use it, and hit a pile of excellent dij again with my hands.
code:
spfa version
uses math; var edge : array[0..400000] of record t, len, next : longint; end; head, dis, q : array[0..400000] of int64; vis : array[0..200000] of boolean; n, m, pb, pa1, pa2, x, y, z, ans, num, i : longint; procedure swap(var x, y : int64); var tmp : int64; begin tmp := x; x := y; y := tmp; end; procedure add(x, y, z : longint); begin inc(num); edge[num].t := y; edge[num].len := z; edge[num].next := head[x]; head[x] := num; end; procedure spfa(s : longint); var h, t, e, i, u, sum : longint; begin for i := 1 to n do dis[i] := maxlongint; dis[s] := 0; fillchar(vis, sizeof(vis), 0); h := 0; t := 1; q[1] := s; while h < t do begin inc(h); e := q[h]; vis[e] := false; i := head[e]; while i <> 0 do begin u := edge[i].t; if dis[u] > dis[e] + edge[i].len then begin dis[u] := dis[e] + edge[i].len; if not vis[u] then begin inc(t); q[t] := u; if dis[u] < dis[q[h + 1]] then swap(q[t], q[h + 1]); end; end; i := edge[i].next; end; end; sum := dis[pb]; if s <> pa1 then inc(sum, dis[pa1]) else inc(sum, dis[pa2]); ans := min(ans, sum); end; begin readln(m, n, pb, pa1, pa2); for i := 1 to m do begin readln(x, y, z); add(x, y, z); add(y, x, z); end; ans := maxlongint; spfa(pa1); spfa(pa2); writeln(ans); end.
dijkstra version
uses math; var edge : array[0..400000] of record t, len, next : longint; end; heap : array[0..400000] of record node, len : int64; end; head, dis : array[0..400000] of int64; vis : array[0..200000] of boolean; n, m, pb, pa1, pa2, x, y, z, ans, num, i, len : longint; procedure swap(var x, y : int64); var tmp : int64; begin tmp := x; x := y; y := tmp; end; procedure add(x, y, z : longint); begin inc(num); edge[num].t := y; edge[num].len := z; edge[num].next := head[x]; head[x] := num; end; procedure push(u, l : int64); var i : longint; begin inc(len); i := len; heap[i].node := u; heap[i].len := l; while i > 1 do begin if heap[i].len < heap[i >> 1].len then begin swap(heap[i].node, heap[i >> 1].node); swap(heap[i].len, heap[i >> 1].len); i := i >> 1; end else break; end; end; procedure pop; var i, x : longint; begin heap[1] := heap[len]; dec(len); i := 1; while (i << 1) <= len do begin if ((i << 1) or 1 > len) or (heap[i << 1].len < heap[(i << 1) or 1].len) then x := i << 1 else x := (i << 1) or 1; if heap[i].len > heap[x].len then begin swap(heap[i].node, heap[x].node); swap(heap[i].len, heap[x].len); i := x; end else break; end; end; procedure dijkstra(s : longint); var u, l, v, sum : int64; i : longint; begin for i := 1 to n do dis[i] := maxlongint; dis[s] := 0; fillchar(vis, sizeof(vis), 0); len := 0; push(s, 0); while len > 0 do begin u := heap[1].node; l := heap[1].len; pop; if vis[u] then continue; vis[u] := true; i := head[u]; while i <> 0 do begin v := edge[i].t; if dis[v] > l + edge[i].len then begin dis[v] := l + edge[i].len; push(v, dis[v]); end; i := edge[i].next; end; end; sum := dis[pb]; if s <> pa1 then inc(sum, dis[pa1]) else inc(sum, dis[pa2]); ans := min(ans, sum); end; begin readln(m, n, pb, pa1, pa2); for i := 1 to m do begin readln(x, y, z); add(x, y, z); add(y, x, z); end; ans := maxlongint; dijkstra(pa1); dijkstra(pa2); writeln(ans); end.