最短路求方案数
最短路求方案数
整体思路:
- 首先引入拓扑序的概念:计算当前状态时,当前状态所依赖的状态都已经计算出来了
- 类似DP,先求出全局最小值,再分别求出每个子集中等于全局最小值的元素数量,和最短路的唯一区别是,DP是在拓扑图中做最短路,但普通的最短路中可能存在环
- 若将最短路的模型转化为拓扑图,则可以用类似DP的方式处理求方案数的问题
- 其次引入最短路树(最短路拓扑图)
- 概念:记录每个点是由哪个点更新来的,即若
dist[j] = dist[t] + w[i] (t -> j)
,j 可由 t 更新而来。 - 如果没有任何限制,则可能存在权值为0的环,可以在此环上转无限次,则最短路径的方案数为 INF,相当于无解了,求不出确切的树。
- 所以,如果想要求最短路的方案数,则图中不能存在权值为0的环,依照上述方案记录路径,即可形成拓扑图,简单地说,将可以求最短路时可以被利用的边保存(可更新最短路径上的点的边保存),其余边去掉。
- 概念:记录每个点是由哪个点更新来的,即若
分析算法:
求最短路的算法系列:
热知识:判断是否满足拓扑序,此点不能更新之前已更新的点,反之则形成环,非拓扑序
- BFS系列(bfs)
- 一层一层扩展,保证每个点只入队一次,且只出队一次,满足拓扑序
- Dijkstra系列(朴素dijkstra,堆优化dijkstra,双端队列广搜)
- 每个点只作为最小值出队一次,之前出现的点的距离一定小于等于该点的距离,所以此点一定不会更新之前的点,满足拓扑序
- Bellman-ford系列(Bellman-ford,spfa)
- 按照边更新,一个点出队都无法确定其为最小值,每个点可能入队多次,本身不具备拓扑序,若使用则需先用spfa算法预处理出来最短路径,建立最短路径树,然后在最短路径树上跑bfs等算法。
总结:bfs系列和dijkstra系列算法可以直接做,spfa比较麻烦需要预处理。
代码如下:
1 | void bfs() |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Moench 的算法宝库!