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.

 

posted on 2013-12-20 15:13  BLADEVIL  阅读(428)  评论(0编辑  收藏  举报