给定一个图和两个节点u和v ,任务是使用 Floyd Warshall 算法打印 u 和 v 之间的最短路径。
例子:
Input: u = 1, v = 3
Output: 1 -> 2 -> 3
Explanation:
Shortest path from 1 to 3 is through vertex 2 with total cost 3.
The first edge is 1 -> 2 with cost 2 and the second edge is 2 -> 3 with cost 1.
Input: u = 0, v = 2
Output: 0 -> 1 -> 2
Explanation:
Shortest path from 0 to 2 is through vertex 1 with total cost = 5
方法:
- 这里的主要思想是使用一个矩阵(二维数组),如果任何一对节点的最短路径发生变化,该矩阵将跟踪下一个要指向的节点。最初,任意两个节点 u 和 v 之间的最短路径是 v(即从 u -> v 的直接边)。
- 初始化Next数组
If the path exists between two nodes then Next[u][v] = v
else we set Next[u][v] = -1
- Floyd Warshall 算法的修改
Inside the if condition of Floyd Warshall Algorithm we’ll add a statement Next[i][j] = Next[i][k]
(that means we found the shortest path between i, j through an intermediate node k).
- 这就是我们的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
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]
# Print the 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
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
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 算法会很有效。
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live