【題解】LuoGu3003:[USACO10DEC]蘋果交貨Apple Delivery
原題傳送門 貝西有兩個又香又脆的紅蘋果要送給她的兩個朋友。當然她可以走的C(1<=C<=200000)條“牛路”都被包含在一種常用的圖中,包含了P(1<=P<=100000)個牧場,分別被標為1…P。沒有“牛路”會從一個牧場又走回它自己。“牛路”是雙向的,每條牛路都會被標上一個距離。最重要的是,每個牧場都可以通向另一個牧場。每條牛路都連線著兩個不同的牧場P1_i和P2_i(1<=P1_i,p2_i<=P),距離為D_i。所有“牛路”的距離之和不大於2000000000。
現在,貝西要從牧場PB開始給PA_1和PA_2牧場各送一個蘋果(PA_1和PA_2順序可以調換),那麼最短的距離是多少呢?當然,PB、PA_1和PA_2各不相同。
輸入輸出格式 輸入格式:
-
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
輸出格式:
- Line 1: The shortest distance Bessie must travel to deliver both apples 輸入樣例 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 輸出樣例 12
這道題是裸的最短路, 貝茜的走法只有兩種:pb->pa1->pa2或pb->pa2->pa1 所以我們只需算出每個點到pa1、pa2的最短路即可
But,本題資料範圍有點大,作為一個pascal選手,懶得打堆優dij(手打堆可真麻煩),就寫寫SPFA吧。spfa太不穩定了,所以我想起了看到過的一個優化版SPFA,
即:若新加入到隊尾的點到源點的最短路小於隊首的,則給它加入到隊首 實現code(其中u為新加入節點):
if dis[u] < dis[q[h + 1]] then swap(q[t], q[h + 1]);
嗯,就加了這麼一句話時間上優化了很多,不過spfa在考場上還是太虛,我不敢用,又手打了一遍堆優dij的
code: spfa版本
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版本
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.