使用修改的floyd warshall打印给定节点的最短路径b / w

时间:2013-11-06 13:45:43

标签: c++ algorithm shortest-path floyd-warshall

我读了Wikipedia给出的方法,通过修改Floyd Warshall算法,在图中的两个给定点打印短路径b / w。我编写了这个,但它并没有真正给出预期的输出:

  1. minimumDistanceMatrix[i][j]中的所有元素初始化为图表中的各个权重,将矩阵shortestPathCalculatorMatrix [i][j]中的所有元素初始化为-1。

  2. 然后:

    // Find shortest path using Floyd–Warshall algorithm
    
    for ( unsigned int k = 0 ; k < getTotalNumberOfCities() ; ++ k)
       for ( unsigned int i = 0 ; i < getTotalNumberOfCities() ; ++ i)
          for ( unsigned int j = 0 ; j < getTotalNumberOfCities() ; ++ j)
              if ( minimumDistanceMatrix[i][k] + minimumDistanceMatrix[k][j] < minimumDistanceMatrix[i][j] )
              {
                    minimumDistanceMatrix[i][j] = minimumDistanceMatrix[i][k] + minimumDistanceMatrix[k][j];
                    shortestPathCalculatorMatrix [i][j] =  k;
              }
    
  3. 然后:

    void CitiesMap::findShortestPathListBetween(int source , int destination) 
    {
         if( source == destination || source < 0 || destination < 0)
            return;
    
         if( INFINITY == getShortestPathBetween(source,destination) )
            return ;
    
         int intermediate = shortestPathCalculatorMatrix[source][destination];
    
         if( -1 == intermediate )
         {
            pathCityList.push_back( destination );
            return ;
         }
    
         else
         {
            findShortestPathListBetween( source, intermediate ) ;
            pathCityList.push_back(intermediate);
            findShortestPathListBetween( intermediate, destination ) ;
    
            return ;
         }
    }
    
  4. P.S:pathCityList是一个向量,在调用findShortestPathListBetween之前假定为空。在此调用结束时,此向量包含其中的所有中间节点。

    有人可以指出我可能出错的地方吗?

3 个答案:

答案 0 :(得分:8)

更容易(也更直接)不迭代索引而是遍历顶点。此外,每个前任(通常表示为π,而不是next),需要指向它的前任,而不是当前的临时顶点。

给出| V |×| V |邻接矩阵dist用于距离,初始化为无穷大,以及| V |×| V |邻接矩阵next to to vertters to vertices,

for each vertex v
    dist[v, v] ← 0
for each edge (u,v)
    dist[u, v] ← w(u,v)  // the weight of the edge (u,v)
    next[u, v] ← u

for each vertex k
    for each vertex i
        for each vertex j
            if dist[i, k] + dist[k, j] < dist[i, j] then
                dist[i, j] ← dist[i, k] + dist[k, j]
                next[i, j] ← next[k, j]

请注意,我已经更改了三个嵌套循环以迭代顶点而不是索引,并且我修复了最后一行以引用前一个节点而不是任何中间节点。

上面的实现看起来几乎就像伪代码一样,例如,可以在scipy.sparse.csgraph中找到。

路径重建从最后开始(j在下面的代码中)并跳转到j的前身(next[i, j]),直到它达到i

function path(i, j)
    if i = j then
        write(i)
    else if next[i, j] = NIL then
        write("no path exists")
    else
        path(i, next[i, j])
        write(j)

答案 1 :(得分:0)

有点晚了,但是上面的代码还是有缺陷的....不应是next[i][j]=next[k][j],但是找到它的正确代码是next[i][j]=next[i][k]

在示例输入中自己尝试一下,您将了解为什么它起作用以及为什么前一个输入错误

答案 2 :(得分:0)

这是下面的实现。 Why don't try a problem on it!享受CP!

   // g[][] is the graph
   // next[i][j] stores vertex next to i in the shortest path between (i,j)
      for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
          if(g[i][j]==0)g[i][j]=inf;  // there is no edge b/w (i,j)
          else next[i][j]=j;    // if there is an edge b/w i and j then j should be next to i
        }
      }

      for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
          for(int j=1;j<=n;j++){
            if(g[i][j]>g[i][k]+g[k][j]){
              g[i][j]=g[i][k]+g[k][j];
              next[i][j]=next[i][k];  // we found a vertx k next to i which further decrease the shortest path b/w (i,j) so updated it
            }
          }
        }
      }
      // for printing path
      for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
          int u=i,v=j;
          print(u+" ");
          while(u!=v){
            u=next[u][v];
            print(u+" ");
          }
          print("\n");
        }
      }