给定一个图以及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
方法:
- 这里的主要思想是使用matrix(2D array),如果最短路径对任何一对节点都发生更改,它将跟踪下一个要指向的节点。最初,u和v的任何两个节点之间的最短路径是v(即u-> v的直接边)。
- 初始化下一个数组
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
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算法会比较有效。