📌  相关文章
📜  使用Floyd Warshall算法查找任何两个节点之间的最短路径

📅  最后修改于: 2021-04-21 22:55:46             🧑  作者: Mango

给定一个以及uv两个节点,任务是使用Floyd Warshall算法打印u和v之间的最短路径。
例子:

方法:

  • 这里的主要思想是使用matrix(2D array),如果最短路径对任何一对节点都发生更改,它将跟踪下一个要指向的节点。最初,u和v的任何两个节点之间的最短路径是v(即u-> v的直接边)。
  • 初始化下一个数组
  • Floyd Warshall算法的修改
  • 这就是我们的if条件的样子
if(dis[i][j] > dis[i][k] + dis[k][j])
{
    dis[i][j] = dis[i][k] + dis[k][j];
    Next[i][j] = Next[i][k];    
}
  • 为了使用这些节点构造路径,我们将简单地开始遍历节点u,同时将其值更新为next [u] [v],直到到达节点v为止。
path = [u]
while u != v:
    u = Next[u][v]
    path.append(u)

下面是上述方法的实现。

C++
// C++ program to find the shortest
// path between any two nodes using
// Floyd Warshall Algorithm.
#include 
using namespace std;
 
#define MAXN 100
// Infinite value for array
const int INF = 1e7;
 
int dis[MAXN][MAXN];
int Next[MAXN][MAXN];
 
// Initializing the distance and
// Next array
void initialise(int V,
                vector >& graph)
{
    for (int i = 0; i < V; i++) {
        for (int j = 0; j < V; j++) {
            dis[i][j] = graph[i][j];
 
            // No edge between node
            // i and j
            if (graph[i][j] == INF)
                Next[i][j] = -1;
            else
                Next[i][j] = j;
        }
    }
}
 
// Function construct the shotest
// path between u and v
vector constructPath(int u,
                        int v)
{
    // If there's no path between
    // node u and v, simply return
    // an empty array
    if (Next[u][v] == -1)
        return {};
 
    // Storing the path in a vector
    vector path = { u };
    while (u != v) {
        u = Next[u][v];
        path.push_back(u);
    }
    return path;
}
 
// Standard Floyd Warshall Algorithm
// with little modification Now if we find
// that dis[i][j] > dis[i][k] + dis[k][j]
// then we modify next[i][j] = next[i][k]
void floydWarshall(int V)
{
    for (int k = 0; k < V; k++) {
        for (int i = 0; i < V; i++) {
            for (int j = 0; j < V; j++) {
 
                // We cannot travel through
                // edge that doesn't exist
                if (dis[i][k] == INF
                    || dis[k][j] == INF)
                    continue;
 
                if (dis[i][j] > dis[i][k]
                                    + dis[k][j]) {
                    dis[i][j] = dis[i][k]
                                + dis[k][j];
                    Next[i][j] = Next[i][k];
                }
            }
        }
    }
}
 
// Print the shortest path
void printPath(vector& path)
{
    int n = path.size();
    for (int i = 0; i < n - 1; i++)
        cout << path[i] << " -> ";
    cout << path[n - 1] << endl;
}
 
// Driver code
int main()
{
 
    int V = 4;
    vector > graph
        = { { 0, 3, INF, 7 },
            { 8, 0, 2, INF },
            { 5, INF, 0, 1 },
            { 2, INF, INF, 0 } };
 
    // Function to initialise the
    // distance and Next array
    initialise(V, graph);
 
    // Calling Floyd Warshall Algorithm,
    // this will update the shortest
    // distance as well as Next array
    floydWarshall(V);
    vector path;
 
    // Path from node 1 to 3
    cout << "Shortest path from 1 to 3: ";
    path = constructPath(1, 3);
    printPath(path);
 
    // Path from node 0 to 2
    cout << "Shortest path from 0 to 2: ";
    path = constructPath(0, 2);
    printPath(path);
 
    // path from node 3 to 2
    cout << "Shortest path from 3 to 2: ";
    path = constructPath(3, 2);
    printPath(path);
 
    return 0;
}


Java
// Java program to find the shortest
// path between any two nodes using
// Floyd Warshall Algorithm.
import java.util.*;
 
class GFG{
 
static final int MAXN = 100;
 
// Infinite value for array
static int INF = (int) 1e7;
 
static int [][]dis = new int[MAXN][MAXN];
static int [][]Next = new int[MAXN][MAXN];
 
// Initializing the distance and
// Next array
static void initialise(int V,
                    int [][] graph)
{
    for(int i = 0; i < V; i++)
    {
    for(int j = 0; j < V; j++)
    {
        dis[i][j] = graph[i][j];
             
        // No edge between node
        // i and j
        if (graph[i][j] == INF)
            Next[i][j] = -1;
        else
            Next[i][j] = j;
    }
    }
}
 
// Function conthe shotest
// path between u and v
static Vector constructPath(int u,
                                    int v)
{
 
    // If there's no path between
    // node u and v, simply return
    // an empty array
    if (Next[u][v] == -1)
        return null;
 
    // Storing the path in a vector
    Vector path = new Vector();
    path.add(u);
     
    while (u != v)
    {
        u = Next[u][v];
        path.add(u);
    }
    return path;
}
 
// Standard Floyd Warshall Algorithm
// with little modification Now if we find
// that dis[i][j] > dis[i][k] + dis[k][j]
// then we modify next[i][j] = next[i][k]
static void floydWarshall(int V)
{
    for(int k = 0; k < V; k++)
    {
    for(int i = 0; i < V; i++)
    {
        for(int j = 0; j < V; j++)
        {
             
            // We cannot travel through
            // edge that doesn't exist
            if (dis[i][k] == INF ||
                dis[k][j] == INF)
                continue;
                 
            if (dis[i][j] > dis[i][k] +
                            dis[k][j])
            {
                dis[i][j] = dis[i][k] +
                            dis[k][j];
                Next[i][j] = Next[i][k];
            }
        }
    }
    }
}
 
// Print the shortest path
static void printPath(Vector path)
{
    int n = path.size();
    for(int i = 0; i < n - 1; i++)
    System.out.print(path.get(i) + " -> ");
    System.out.print(path.get(n - 1) + "\n");
}
 
// Driver code
public static void main(String[] args)
{
    int V = 4;
    int [][] graph = { { 0, 3, INF, 7 },
                    { 8, 0, 2, INF },
                    { 5, INF, 0, 1 },
                    { 2, INF, INF, 0 } };
 
    // Function to initialise the
    // distance and Next array
    initialise(V, graph);
 
    // Calling Floyd Warshall Algorithm,
    // this will update the shortest
    // distance as well as Next array
    floydWarshall(V);
    Vector path;
 
    // Path from node 1 to 3
    System.out.print("Shortest path from 1 to 3: ");
    path = constructPath(1, 3);
    printPath(path);
 
    // Path from node 0 to 2
    System.out.print("Shortest path from 0 to 2: ");
    path = constructPath(0, 2);
    printPath(path);
 
    // Path from node 3 to 2
    System.out.print("Shortest path from 3 to 2: ");
    path = constructPath(3, 2);
    printPath(path);
}
}
 
// This code is contributed by Amit Katiyar


C#
// C# program to find the shortest
// path between any two nodes using
// Floyd Warshall Algorithm.
using System;
using System.Collections.Generic;
 
class GFG{
 
static readonly int MAXN = 100;
 
// Infinite value for array
static int INF = (int)1e7;
 
static int [,]dis = new int[MAXN, MAXN];
static int [,]Next = new int[MAXN, MAXN];
 
// Initializing the distance and
// Next array
static void initialise(int V,
                       int [,] graph)
{
    for(int i = 0; i < V; i++)
    {
        for(int j = 0; j < V; j++)
        {
            dis[i, j] = graph[i, j];
                 
            // No edge between node
            // i and j
            if (graph[i, j] == INF)
                Next[i, j] = -1;
            else
                Next[i, j] = j;
        }
    }
}
 
// Function conthe shotest
// path between u and v
static List constructPath(int u, int v)
{
     
    // If there's no path between
    // node u and v, simply return
    // an empty array
    if (Next[u, v] == -1)
        return null;
 
    // Storing the path in a vector
    List path = new List();
    path.Add(u);
     
    while (u != v)
    {
        u = Next[u, v];
        path.Add(u);
    }
    return path;
}
 
// Standard Floyd Warshall Algorithm
// with little modification Now if we find
// that dis[i,j] > dis[i,k] + dis[k,j]
// then we modify next[i,j] = next[i,k]
static void floydWarshall(int V)
{
    for(int k = 0; k < V; k++)
    {
        for(int i = 0; i < V; i++)
        {
            for(int j = 0; j < V; j++)
            {
                 
                // We cannot travel through
                // edge that doesn't exist
                if (dis[i, k] == INF || 
                    dis[k, j] == INF)
                    continue;
                    
                if (dis[i, j] > dis[i, k] +
                                dis[k, j])
                {
                    dis[i, j] = dis[i, k] + 
                                dis[k, j];
                    Next[i, j] = Next[i, k];
                }
            }
        }
    }
}
 
// Print the shortest path
static void printPath(List path)
{
    int n = path.Count;
     
    for(int i = 0; i < n - 1; i++)
        Console.Write(path[i] + " -> ");
        
    Console.Write(path[n - 1] + "\n");
}
 
// Driver code
public static void Main(String[] args)
{
    int V = 4;
    int [,] graph = { { 0, 3, INF, 7 },
                      { 8, 0, 2, INF },
                      { 5, INF, 0, 1 },
                      { 2, INF, INF, 0 } };
 
    // Function to initialise the
    // distance and Next array
    initialise(V, graph);
 
    // Calling Floyd Warshall Algorithm,
    // this will update the shortest
    // distance as well as Next array
    floydWarshall(V);
    List path;
 
    // Path from node 1 to 3
    Console.Write("Shortest path from 1 to 3: ");
    path = constructPath(1, 3);
    printPath(path);
 
    // Path from node 0 to 2
    Console.Write("Shortest path from 0 to 2: ");
    path = constructPath(0, 2);
    printPath(path);
 
    // Path from node 3 to 2
    Console.Write("Shortest path from 3 to 2: ");
    path = constructPath(3, 2);
    printPath(path);
}
}
 
// This code is contributed by Amit Katiyar


Python3
# Python3 program to find the shortest
# path between any two nodes using
# Floyd Warshall Algorithm.
 
# Initializing the distance and
# Next array
def initialise(V):
    global dis, Next
 
    for i in range(V):
        for j in range(V):
            dis[i][j] = graph[i][j]
 
            # No edge between node
            # i and j
            if (graph[i][j] == INF):
                Next[i][j] = -1
            else:
                Next[i][j] = j
 
# Function construct the shotest
# path between u and v
def constructPath(u, v):
    global graph, Next
     
    # If there's no path between
    # node u and v, simply return
    # an empty array
    if (Next[u][v] == -1):
        return {}
 
    # Storing the path in a vector
    path = [u]
    while (u != v):
        u = Next[u][v]
        path.append(u)
 
    return path
 
# Standard Floyd Warshall Algorithm
# with little modification Now if we find
# that dis[i][j] > dis[i][k] + dis[k][j]
# then we modify next[i][j] = next[i][k]
def floydWarshall(V):
    global dist, Next
    for k in range(V):
        for i in range(V):
            for j in range(V):
                 
                # We cannot travel through
                # edge that doesn't exist
                if (dis[i][k] == INF or dis[k][j] == INF):
                    continue
                if (dis[i][j] > dis[i][k] + dis[k][j]):
                    dis[i][j] = dis[i][k] + dis[k][j]
                    Next[i][j] = Next[i][k]
 
# Prthe shortest path
def printPath(path):
    n = len(path)
    for i in range(n - 1):
        print(path[i], end=" -> ")
    print (path[n - 1])
 
# Driver code
if __name__ == '__main__':
    MAXM,INF = 100,10**7
    dis = [[-1 for i in range(MAXM)] for i in range(MAXM)]
    Next = [[-1 for i in range(MAXM)] for i in range(MAXM)]
 
    V = 4
    graph = [ [ 0, 3, INF, 7 ],
            [ 8, 0, 2, INF ],
            [ 5, INF, 0, 1 ],
            [ 2, INF, INF, 0 ] ]
 
    # Function to initialise the
    # distance and Next array
    initialise(V)
 
    # Calling Floyd Warshall Algorithm,
    # this will update the shortest
    # distance as well as Next array
    floydWarshall(V)
    path = []
 
    # Path from node 1 to 3
    print("Shortest path from 1 to 3: ", end = "")
    path = constructPath(1, 3)
    printPath(path)
 
    # Path from node 0 to 2
    print("Shortest path from 0 to 2: ", end = "")
    path = constructPath(0, 2)
    printPath(path)
 
    # Path from node 3 to 2
    print("Shortest path from 3 to 2: ", end = "")
    path = constructPath(3, 2)
    printPath(path)
 
    # This code is contributed by mohit kumar 29


输出:
Shortest path from 1 to 3: 1 -> 2 -> 3
Shortest path from 0 to 2: 0 -> 1 -> 2
Shortest path from 3 to 2: 3 -> 0 -> 1 -> 2

复杂度分析:

  • Floyd Warshall算法的时间复杂度为O(V 3 )
  • 为了找到最短路径,每个查询的时间复杂度为O(V)

注意:当图形包含数百个顶点并且您需要回答与最短路径有关的多个查询时,使用Floyd Warshall算法会比较有效。