bzoj 2662&bzoj 2763 SPFA变形

我们用dis[i,j]代表到i这个点,用j张票的最短路程,那么我们只需要在SPFA更新

的时候,用dis[i,j]更新dis[p,j]和dis[p,j+1]就行了

/**************************************************************

    Problem: 2662

    User: BLADEVIL

    Language: Pascal

    Result: Accepted

    Time:4 ms

    Memory:376 kb

****************************************************************/

 

//By BLADEVIL

type

    rec                         =record

        x, use                  :longint;

    end;

     

var

    n, m, k                     :longint;

    pre, other, len             :array[0..2010] of longint;

    last                        :array[0..100] of longint;

    l                           :longint;

    dis                         :array[0..100,0..100] of longint;

    flag                        :array[0..100,0..100] of boolean;

    que                         :array[0..10000] of rec;

    ans                         :longint;

     

function min(a,b:longint):longint;

begin

    if a>b then min:=b else min:=a;

end;

     

procedure connect(x,y,z:longint);

begin

    inc(l);

    pre[l]:=last[x];

    last[x]:=l;

    other[l]:=y;

    len[l]:=z;

end;

     

procedure init;

var

    i                           :longint;

    x, y, z                     :longint;

begin

    read(n,m,k);

    for i:=1 to m do

    begin

        read(x,y,z);

        connect(x,y,z);

        connect(y,x,z);

    end;

end;

 

procedure main;

var

    h, t, q, p                  :longint;

    cur, ti                     :longint;

    i                           :longint;

     

begin

    filldword(dis,sizeof(dis) div 4,maxlongint div 10);

    dis[1,0]:=0;

    h:=0; t:=1;

    que[1].x:=1; que[1].use:=0;

    while h<>t do

    begin

        h:=h mod 10000+1;

        cur:=que[h].x;

        ti:=que[h].use;

        flag[cur,ti]:=false;

        q:=last[cur];

        while q<>0 do

        begin

            p:=other[q];

            if dis[cur,ti]+len[q]<dis[p,ti] then

            begin

                dis[p,ti]:=dis[cur,ti]+len[q];

                if not flag[p,ti] then

                begin

                    t:=t mod 10000+1;

                    que[t].x:=p; que[t].use:=ti;

                    flag[p,ti]:=true;

                end;

            end;

            if ti<k then

            begin

                if dis[cur,ti]+len[q] div 2<dis[p,ti+1] then

                begin

                    dis[p,ti+1]:=dis[cur,ti]+len[q] div 2;

                    if not flag[p,ti+1] then

                    begin

                        t:=t mod 10000+1;

                        que[t].x:=p; que[t].use:=ti+1;

                        flag[p,ti+1]:=true;

                    end;

                end;

            end;

            q:=pre[q];

        end;

    end;

    ans:=maxlongint;

    for i:=0 to k do ans:=min(ans,dis[n,i]);

    writeln(ans);

end;

 

begin

    init;

    main;

end.

 

/**************************************************************

    Problem: 2763

    User: BLADEVIL

    Language: Pascal

    Result: Accepted

    Time:9472 ms

    Memory:2804 kb

****************************************************************/

 

//By BLADEVIL

type

    rec                         =record

        x, use                  :longint;

    end;

     

var

    n, m, k                     :longint;

    pre, other, len             :array[0..100010] of longint;

    last                        :array[0..10010] of longint;

    l                           :longint;

    dis                         :array[0..10000,0..11] of longint;

    flag                        :array[0..10000,0..11] of boolean;

    que                         :array[0..100010] of rec;

    ans                         :longint;

    st, fin                     :longint;

     

function min(a,b:longint):longint;

begin

    if a>b then min:=b else min:=a;

end;

     

procedure connect(x,y,z:longint);

begin

    inc(l);

    pre[l]:=last[x];

    last[x]:=l;

    other[l]:=y;

    len[l]:=z;

end;

     

procedure init;

var

    i                           :longint;

    x, y, z                     :longint;

begin

    read(n,m,k);

    read(st,fin);

    for i:=1 to m do

    begin

        read(x,y,z);

        connect(x,y,z);

        connect(y,x,z);

    end;

end;

 

procedure main;

var

    h, t, q, p                  :longint;

    cur, ti                     :longint;

    i                           :longint;

     

begin

    filldword(dis,sizeof(dis) div 4,maxlongint div 10);

    dis[st,0]:=0;

    h:=0; t:=1;

    que[1].x:=st; que[1].use:=0;

    while h<>t do

    begin

        h:=h mod 100000+1;

        cur:=que[h].x;

        ti:=que[h].use;

        flag[cur,ti]:=false;

        q:=last[cur];

        while q<>0 do

        begin

            p:=other[q];

            if dis[cur,ti]+len[q]<dis[p,ti] then

            begin

                dis[p,ti]:=dis[cur,ti]+len[q];

                if not flag[p,ti] then

                begin

                    t:=t mod 100000+1;

                    que[t].x:=p; que[t].use:=ti;

                    flag[p,ti]:=true;

                end;

            end;

            if ti<k then

            begin

                if dis[cur,ti]<dis[p,ti+1] then

                begin

                    dis[p,ti+1]:=dis[cur,ti];

                    if not flag[p,ti+1] then

                    begin

                        t:=t mod 100000+1;

                        que[t].x:=p; que[t].use:=ti+1;

                        flag[p,ti+1]:=true;

                    end;

                end;

            end;

            q:=pre[q];

        end;

    end;

    ans:=maxlongint;

    for i:=0 to k do ans:=min(ans,dis[fin,i]);

    writeln(ans);

end;

 

begin

    init;

    main;

end.

 

你可能感兴趣的:(SPFA)