bzoj 1706 倍增floyd

61 篇文章 0 订阅
6 篇文章 0 订阅

题意:给定一张无向图,求从s到e恰好经过n条边的最短路

倍增floyd

Floyd是通过插入点的方法来找到最短路的,很适合此题,跑n遍floyd的就可以了

显然这样做是T的

我们将n进行二进制拆分,类似于快速幂的思想

map[p][i][j]表示刚好经过2^p条边从j到k的最短距离,

易知 map[p][i][j]=min{map[p-1][i][j]+map[p-1][i][j]}。

若n and 1 =1,则让答案数组f和map跑floyd(即 min{g[p-1][i][k]+map[p-1][k][j]}),

否则map自己和自己跑(min{map[p-1][i][k]+dist[p-1][k][j]})

更新n n=n >>1

非正常人类的编号我们只需要离散化一下就可以了

注意答案数组f的初始化同floyd,但map数组的初始化中 map[i,i]<>0 ,因为如果等于0的话它相当于停在那里并没有多一条边

初始化为(maxlongint div 10)居然废了,fillchar(63)就过了,mdzz,害我改了一个多小时


type
        rec=array[0..110,0..110] of longint;
var
        n,m,s,t,num,x,y,len:longint;
        map,f,c            :rec;
        vis                :array[0..1010] of longint;
        i,j                :longint;
function min (a,b:longint):longint;
begin
   if a<b then exit(a) else exit(b);
end;

procedure floyd(var a,b:rec);
var
        i,j,k:longint;
begin
   fillchar(c,sizeof(c),63);
   for k:=1 to num do
     for i:=1 to num do
       for j:=1 to num do
         c[i,j]:=min(c[i,j],a[i,k]+b[k,j]);
   a:=c;
end;

procedure work(x:longint);
begin
   while (x>0) do
   begin
      if (x and 1=1) then floyd(f,map);
      floyd(map,map);
      x:=x >>1;
   end;
end;

begin
   read(n,m,s,t);
   num:=0;
   fillchar(map,sizeof(map),63);
   fillchar(f,sizeof(f),63);
   for i:=1 to m do
   begin
      read(len,x,y);
      if vis[x]=0 then
      begin
         inc(num); vis[x]:=num;
      end;
      if vis[y]=0 then
      begin
         inc(num); vis[y]:=num;
      end;
      map[vis[x],vis[y]]:=len;
      map[vis[y],vis[x]]:=len;
   end;
   for i:=1 to num do f[i,i]:=0;
   work(n);
   writeln(f[vis[s],vis[t]]);
end.


—— by Eirlys








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值