bzoj 3245 spfa

来源:互联网 发布:手机shell是什么软件 编辑:程序博客网 时间:2024/06/05 15:02

题意:n个点,编号为0~n-1,m条有向边,限速不为0的边按照限速前进,限速为0的边按进入这条道路时的速度前进(即到该条边起点的速度),给定终点,初始起点为点0,初始速度为70,问从点0到终点最快时间的路径

可以理解成拆点的spfa

dis[i,j]表示到达第i个点的速度为j,spfa更新时讨论该边的速度是否为0分别按两种方法更新

每次更新dis[i,j]时,记录转移来的点和转移来的速度注意并不是入队的时候才更新,并且要两个都记录,只记录转移来的点的话会出事情...mdzz

var        n,m,st,x,y,z,w  :longint;        minn,l,tot      :longint;        i               :longint;        ans             :double;        pre,other,len,v :array[0..50010] of longint;        dis             :array[0..200,0..510] of double;        vis             :array[0..200,0..510] of boolean;        que             :array[0..75010,0..1] of longint;        last,way        :array[0..200] of longint;        fromn,fromv     :array[0..200,0..510] of longint;procedure connect(x,y,vv,z:longint);begin   inc(l);   pre[l]:=last[x];   last[x]:=l;   other[l]:=y;   len[l]:=z;   v[l]:=vv;end;procedure spfa;var        h,tmp,tl,cur,p,q:longint;begin   fillchar(dis,sizeof(dis),127);   h:=0; tl:=1;   que[1,0]:=1; que[1,1]:=70;   dis[1,70]:=0;   while (h<>tl) do   begin      h:=h mod 75005+1;      cur:=que[h,0]; tmp:=que[h,1];      vis[cur,tmp]:=false;      q:=last[cur];      while (q<>0) do      begin         p:=other[q];         if v[q]=0 then         begin            if dis[p,tmp]>dis[cur,tmp]+len[q]/tmp then            begin               dis[p,tmp]:=dis[cur,tmp]+len[q]/tmp;               fromn[p,tmp]:=cur;               fromv[p,tmp]:=tmp;               if not vis[p,tmp] then               begin                  vis[p,tmp]:=true;                  tl:=tl mod 75005+1;                  que[tl,0]:=p;                  que[tl,1]:=tmp;               end;            end;         end else         begin            if dis[p,v[q]]>dis[cur,tmp]+len[q]/v[q] then            begin               dis[p,v[q]]:=dis[cur,tmp]+len[q]/v[q];               fromv[p,v[q]]:=tmp;               fromn[p,v[q]]:=cur;               if not vis[p,v[q]] then               begin                  vis[p,v[q]]:=true;                  tl:=tl mod 75005+1;                  que[tl,0]:=p;                  que[tl,1]:=v[q];               end;            end;         end;         q:=pre[q];      end;   end;end;procedure print(x,v:longint);var        y,xx:longint;        i:longint;begin   tot:=0;  xx:=x;   while (x<>-1) do   begin      inc(tot);      way[tot]:=x;      x:=fromn[xx,v];      v:=fromv[xx,v];      xx:=x;   end;   for i:=tot downto 2 do write(way[i]-1,' ');   writeln(way[1]-1);end;begin   read(n,m,st); inc(st);   for i:=1 to m do   begin      read(x,y,z,w);      connect(x+1,y+1,z,w);   end;   fillchar(fromn,sizeof(fromn),255);   spfa;   ans:=maxlongint;   for i:=0 to 500 do     if dis[st,i]<ans then     begin        ans:=dis[st,i];        minn:=i;     end;   print(st,minn);end.
——by Eirlys

0 0