LuoGu3003: [USACO10DEC] Apple Delivery

Keywords: Programming less


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.

Posted by p_h_p on Tue, 29 Jan 2019 11:39:14 -0800