两个节点之间的最短路径递归算法



我正在Scala中递归地实现Dijkstra的最短路径算法,但是我遇到了一些麻烦。我得到了节点32的错误输出,像这样称为shortestPath(3, 2, x, BitSet.empty)。输出6,但正确答案应该是7。我似乎不知道我的代码出了什么问题。

var x = ListBuffer(ListBuffer(0, 2, 3, 4), 
                   ListBuffer(2, 0, 0, 0), 
                   ListBuffer(3, 0, 0, 0), 
                   ListBuffer(4, 0, 0, 0))

我的代码如下所示。

def shortestPath(cur: Int, dest: Int, graph: ListBuffer[ListBuffer[Int]], visited: BitSet) :Int = {
    val newVisited = visited + cur
    if(cur == dest) 0
    else {
      var pathLength = for(i <- graph(cur).indices; if(!visited(i) && graph(cur)(i) > 0)) yield {
          graph(cur)(i) + shortestPath(i, dest, graph, newVisited)
        }
      if (pathLength.isEmpty) 0 else pathLength.min
      }
    }

如obourgain所指出的,代码的临界错误是在两个节点不连接时将最小距离解释为0。

两个节点之间的最小距离应该是无穷大,如果它们断开连接,这是因为两个断开连接的节点的成本必须大于任何连接的节点的成本,对代码的一个简单修复是用Int.MaxValue识别无穷大。

def shortestPath(cur: Int, dest: Int, graph: ListBuffer[ListBuffer[Int]], visited: BitSet) :Int = {
    val newVisited = visited + cur
    if(cur == dest) 0
    else {
        var pathLength = for(i <- graph(cur).indices; if(!visited(i) && graph(cur)(i) > 0)) yield {
            val sLen = shortestPath(i, dest, graph, newVisited)
            if (graph(cur)(i) > Int.MaxValue - sLen) Int.MaxValue else graph(cur)(i) + sLen // change #1
        }
        if (pathLength.isEmpty) Int.MaxValue else pathLength.min // change #2
    }
}

这个修改将在调用shortestPath(3, 2, x, new BitSet())时给出预期的答案Int = 7

以"change #1"注释的代码是为了防止目标节点无法被邻居节点到达时的整数溢出(因此最小距离为Int.MaxValue),而以"change #2"注释的代码是为了在两个节点断开连接时将两个节点之间的最小距离视为"无穷大"。

错误在最后一行:

  if (pathLength.isEmpty) 0 else pathLength.min

如果pathLength.isEmpty,则表示两个点没有连接。但是,该函数返回0,它被解释为权重为0的连接。

最新更新