我有一个加权图G和一对节点s和t。我想找到从s到t的所有路径,边数最少,总成本最低的路径。我不知道该怎么做。以下是我的想法:
我正在考虑找到最短的路径,如果有多条路径,那么我应该比较这些路径的步数。
我想我可以通过将所有边的权重设置为1并计算距离来找到步数。
答案 0 :(得分:0)
从这里开始的合理的第一个猜测是Dijkstra的算法,它可以解决这个问题的每个部分(最小化边数,或最小化总长度)。挑战在于让它同时做到这两点。
通常,在谈论最短路径时,我们认为路径只有一个成本。但是,您可以想象为路径分配两种不同的成本:一种是纯粹基于边数的成本,另一种是纯粹基于这些边的权重的成本。然后,您可以将路径的成本表示为一对(长度,重量),其中长度是路径中的边数,权重是所有这些边的总权重。
想象一下,在图表上运行Dijkstra算法,并进行以下修改。首先,不是跟踪到图中每个节点的候选距离,而是跟踪到每个节点的候选距离的对:候选长度和候选权重。其次,无论何时需要获取最低代码节点,请选择长度最短的节点(不权重)。如果在具有相同长度的多个节点之间存在联系,则通过选择具有最低权重的节点来打破平局。 (如果您已经听说过词典排序,您可以将其视为将(长度,重量)首先按字典顺序排列的节点)。最后,无论何时通过将路径延伸一条边来更新距离,都要将候选长度和候选权重更新到该节点。您可以证明此过程将计算到每个节点的最佳路径,其中" best"表示所有具有最小边数的路径,即成本最低的路径。"
您也可以通过修改图表中边缘的所有成本来实现上述技术。假设图中的最大成本边缘花费为U.然后执行以下操作:将U + 1添加到图形中的所有成本,然后对结果运行Dijkstra算法。这样的净效果是这个新图中的最短路径将是最小化使用的边数的路径。为什么?好吧,每条边都将U + 1加到路径的成本上,而U + 1大于图中任何边的成本,所以如果一条路径比另一条路径便宜,它要么使用至少少一条边,要么它使用相同数量的边缘,但重量更便宜。事实上,你可以证明这种方法基本上与使用权重对的方法相同 - 这是一个很好的练习!
总的来说,这两种方法都将与普通的Dijkstra算法同时运行(O(m + n log n)与Fibonacci堆,O(m log n)与另一种类型的堆) ,这很酷!
答案 1 :(得分:0)
一个节点到另一个节点将是最短路径算法(例如Dijkstra)。 是否使用启发式函数来确定到目标节点的总距离取决于输入。 如果考虑启发式,则可能要选择A *搜索。在这里,您只需要累加每个节点的权重并根据其添加启发式值即可。
如果要获取从任何节点到任何其他节点的所有路径,则可以考虑使用Kruskal或Prim的算法。 两者基本相同,包括修剪。