求最短路时一般比较有名的算法是spfa和dijkstra,而spfa的时间复杂度是玄学(本质上就是bfs加多重更新优化),在某年NOI,出现了SPFA算法死了的情况(卡了40分),堆优化dijkstra是最优秀的,稳定的nlogn复杂度。
不过对于spfa和dijkstra,要注意这两种算法,都是针对单源最短路的,如果要求多源最短路,一种算法是进行n次堆优化dijkstra,复杂度为n^2logn,还有一种非常好写的算法,floyd算法,n^3时间复杂度可以求出所有点对之间的距离。
理解floyd算法其实就是理解动态规划。
定义一个数组 f[k][x][y] ,表示只允许经过结点 1 到 k(这个非常重要),结点 x 到结点 y 的最短路长度。
很显然, f[n][x][y] 就是结点 x 到结点 y 的最短路长度。
考虑怎么求这个数组 f[0][x][y] :边权,或者 0 ,或者 正无穷 ( f[0][x][x] 什么时候应该是 正无穷?) f[k][x][y] = min(f[k-1][x][y], f[k-1][x][k]+f[k-1][k][y])
上面两行都显然是对的,然而这个做法空间是 O(N^3) 。
但我们发现数组的第一维是没有用的,于是可以直接改成 f[x][y] = min(f[x][y], f[x][k]+f[k][y]),因为拿k做过渡点更新的结果,不可能再次用来更新其它以k作为过渡点的点对,所以完全可以把维数压成一维。