从灾后重建看Floyd的本质
本文参考《算法竞赛》。
笔者初次接触 Floyd 是在 zhx 的课上,感觉 zhx 并没有从算法本质出发来解释 Floyd,于是有了这篇文章。
我们都知道 Floyd 的状态设计和转移方程,下面给出转移方程:
现在来考虑这个转移的意义,这里结合《算法竞赛》的原文给出。
想象图中每个点都是一盏灯,开始时所有灯都是灭的。然后逐个点亮灯,点亮第 \(k\) 盏灯,重新计算 \(i,j\) 的最短路,如果经过第 \(k\) 盏灯有最短路径就更新,所有灯都点亮后,计算结束。
此处说的较为省略,笔者加以补充。
我们将状态重新定义为点亮第 \(k\) 盏灯后,\((i,j)\) 之间只经过亮灯的最短路。考虑现在 \((i,j)\) 的最短路可能发生什么变化。由于加入了第 \(k\) 盏灯,我们就有可能会出现一种新的最短路经过 \(k\),即 \(dp_{k-1,i,k}+dp_{k-1,k,j}\),借此更新答案。
关于初始化,如果 \(i\rightarrow j\),那么不点灯时 \((i,j)\) 就存在最短路,\(dp_{0,i,j}=V_{i,j}\);另外,\(dp_{0,i,i}\)。
tips:记录 \(nxt_{i,j}\) 代表 \(u\rightarrow j\) 的最短路上 \(i\) 的下一个点。
Floyd 判断负环
重新修改 \(dp_{k,i,i}\) 的定义为点亮第 \(k\) 盏灯后,\(i\) 经过某些亮灯后回到自己的最短路,初始化为 \(0\),如果在任意时刻出现 \(dp_{k,i,i}<0\),则存在负环。
这里请读者自证,我们主要来说明一下为什么不会影响转移。
显然,如果要在转移中用到 \(dp_{k,i,i}\),只会在 \(k'=i\) 这一阶段用到,从意义上来说,此时断无可能有新路径经过 \(k\),因为我们在 Floyd 中路径不包含起点和终点。所以从 \(dp_{k',i,j}\) 直接转移即可。
楼房重建
我们可以将损坏的楼房视为暗灯,重建的楼房视为亮灯,于是可以离线处理所有操作,按照时间顺序分阶段进行 Floyd 即可。
求解传递闭包
传递闭包本质上就是对于有向图判断 \((i,j)\) 是否连通。
只需修改 Floyd 的定义,改为当前阶段两点是否连通即可,可以发现存在传递性。
或者不修改定义,直接 Floyd 后看两点的最短路径是否为无穷大即可。
前一种方法采用 bitset 优化后接近 \(O(n^2)\)。
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号