先决条件: Dijkstra 最短路径算法
给定一个邻接矩阵图,表示给定图中节点之间的路径。任务是找到具有最少边的最短路径,即如果有多个具有相同成本的短路径,则选择具有最少边数的路径。
考虑下图:
从顶点0到顶点3有两条路径,权重为 12:
- 0 -> 1 -> 2 -> 3
- 0 -> 4 -> 3
因为,Dijkstra 算法是一种贪心算法,它在每次迭代中寻找最小加权顶点,所以原始 Dijkstra 算法将输出第一条路径,但结果应该是第二条路径,因为它包含最少的边数。
例子:
Input: graph[][] = { {0, 1, INFINITY, INFINITY, 10},
{1, 0, 4, INFINITY, INFINITY},
{INFINITY, 4, 0, 7, INFINITY},
{INFINITY, INFINITY, 7, 0, 2},
{10, INFINITY, INFINITY, 2, 0} };
Output: 0->4->3
INFINITY here shows that u and v are not neighbors
Input: graph[][] = { {0, 5, INFINITY, INFINITY},
{5, 0, 5, 10},
{INFINITY, 5, 0, 5},
{INFINITY, 10, 5, 0} };
Output: 0->1->3
方法:该算法的思想是使用原始的 Dijkstra 算法,但也通过一个数组来跟踪路径的长度,该数组存储从源顶点开始的路径长度,因此如果我们找到一条较短的路径同样的重量,那我们就拿走。
让我们按照上面的示例迭代迭代:
考虑我们想要找到从顶点 0 到顶点 3 的最短路径
初始状态:与往常一样,所有顶点的距离和父节点分别为Infinity和NILL 。
但是现在,我们还有一个名为pathlength[] 的数组,它存储从源顶点到所有顶点的路径长度。
最初,我们将pathlength[] 的所有元素设置为0 。
第一次迭代:首先我们寻找包含最小距离的顶点,即顶点0 ,如上图所示。
然后,我们遍历所有没有变黑的邻居,即1和4 。由于顶点1和4的距离是无穷大,因此我们将它们的权重分别减少到1和10 。更新父节点,并将每个顶点( 1和4 )的pathlength[]设置为1,因为它们可以从源顶点通过 1 条边到达。
之后,我们像原始 Dijkstra 算法一样将顶点变黑。
第二次迭代:我们继续寻找包含最小距离的非黑色顶点,即顶点1 ,然后我们将其邻居的权重减少到1 + 4 = 5并像原始 Dijkstra 算法一样更新其父节点,并设置它的pathlength[]到2 ,因为它离源顶点有两条边。
最后,我们将顶点1变黑。
第三次迭代:同样,包含最小距离的非黑化顶点是顶点2 ,因此我们更新非黑化邻居。它有一个未变黑的邻居,即顶点3 。因此,我们将其权重从Infinity更新为5 + 7 = 12,然后将其父节点设置为2 ,并将其路径长度 []设置为3,因为它与源顶点有 3 条边。
最后,我们将顶点2变黑。
第四次迭代:在本次迭代中,算法的行为与原始 Dijkstra 算法不同。我们寻找包含最小距离为4的非黑化顶点。因为,从源顶点到顶点3 的距离是12 (0->1->2->3) 并且顶点4加上边(4, 3) 的距离是12 ,这意味着我们刚刚找到了一个新的从具有相同权重的源顶点到顶点3 的路径。然后,我们检查新路径是否比现有路径更短(在边上),并选择具有最小边的路径。
最后,我们将顶点4变黑。
由于V-1顶点被黑化,算法结束。
下面是上述方法的实现:
C++
// C++ program to find the shortest path
// with minimum edges in a graph
#include
using namespace std;
#define INFINITY 9999
#define n 5
#define s 0
#define d 3
#define NILL -1
int MinDistance(int*, int*);
void PrintPath(int*, int);
// Function to find the shortest path
// with minimum edges in a graph
void Dijkstra(int Graph[n][n], int _n, int _s, int _d)
{
int i, u, v, count;
int dist[n];
int Blackened[n] = { 0 };
int pathlength[n] = { 0 };
int parent[n];
// The parent Of the source vertex is always equal to nill
parent[_s] = NILL;
// first, we initialize all distances to infinity.
for (i = 0; i < n; i++)
dist[i] = INFINITY;
dist[_s] = 0;
for (count = 0; count < n - 1; count++) {
u = MinDistance(dist, Blackened);
// if MinDistance() returns INFINITY, then the graph is not
// connected and we have traversed all of the vertices in the
// connected component of the source vertex, so it can reduce
// the time complexity sometimes
// In a directed graph, it means that the source vertex
// is not a root
if (u == INFINITY)
break;
else {
// Mark the vertex as Blackened
Blackened[u] = 1;
for (v = 0; v < n; v++) {
if (!Blackened[v] && Graph[u][v]
&& dist[u] + Graph[u][v] < dist[v]) {
parent[v] = u;
pathlength[v] = pathlength[parent[v]] + 1;
dist[v] = dist[u] + Graph[u][v];
}
else if (!Blackened[v] && Graph[u][v]
&& dist[u] + Graph[u][v] == dist[v]
&& pathlength[u] + 1 < pathlength[v]) {
parent[v] = u;
pathlength[v] = pathlength[u] + 1;
}
}
}
}
// Printing the path
if (dist[_d] != INFINITY)
PrintPath(parent, _d);
else
cout << "There is no path between vertex "
<< _s << "to vertex " << _d;
}
int MinDistance(int* dist, int* Blackened)
{
int min = INFINITY, min_index, v;
for (v = 0; v < n; v++)
if (!Blackened[v] && dist[v] < min) {
min = dist[v];
min_index = v;
}
return min == INFINITY ? INFINITY : min_index;
}
// Function to print the path
void PrintPath(int* parent, int _d)
{
if (parent[_d] == NILL) {
cout << _d;
return;
}
PrintPath(parent, parent[_d]);
cout << "->" << _d;
}
// Driver code
int main()
{
// INFINITY means that u and v are not neighbors.
int Graph[n][n] = { { 0, 1, INFINITY, INFINITY, 10 },
{ 1, 0, 4, INFINITY, INFINITY },
{ INFINITY, 4, 0, 7, INFINITY },
{ INFINITY, INFINITY, 7, 0, 2 },
{ 10, INFINITY, INFINITY, 2, 0 } };
Dijkstra(Graph, n, s, d);
return 0;
}
Java
// Java program to find the shortest path
// with minimum edges in a graph
import java.io.*;
import java.util.*;
class GFG
{
static int INFINITY = 9999, n = 5, s = 0, d = 3, NILL = -1;
// Function to find the shortest path
// with minimum edges in a graph
static void Dijkstra(int[][] Graph, int _n, int _s, int _d)
{
int i, u, v, count;
int[] dist = new int[n];
int[] Blackened = new int[n];
int[] pathlength = new int[n];
int[] parent = new int[n];
// The parent Of the source vertex is always equal to nill
parent[_s] = NILL;
// first, we initialize all distances to infinity.
for (i = 0; i < n; i++)
dist[i] = INFINITY;
dist[_s] = 0;
for (count = 0; count < n - 1; count++)
{
u = MinDistance(dist, Blackened);
// if MinDistance() returns INFINITY, then the graph is not
// connected and we have traversed all of the vertices in the
// connected component of the source vertex, so it can reduce
// the time complexity sometimes
// In a directed graph, it means that the source vertex
// is not a root
if (u == INFINITY)
break;
else
{
// Mark the vertex as Blackened
Blackened[u] = 1;
for (v = 0; v < n; v++)
{
if (Blackened[v] == 0 && Graph[u][v] != 0
&& dist[u] + Graph[u][v] < dist[v])
{
parent[v] = u;
pathlength[v] = pathlength[parent[v]] + 1;
dist[v] = dist[u] + Graph[u][v];
}
else if (Blackened[v] == 0 && Graph[u][v] != 0
&& dist[u] + Graph[u][v] == dist[v]
&& pathlength[u] + 1 < pathlength[v])
{
parent[v] = u;
pathlength[v] = pathlength[u] + 1;
}
}
}
}
// Printing the path
if (dist[_d] != INFINITY)
PrintPath(parent, _d);
else
System.out.println("There is not path between vertex " +
_s + " to vertex " + _d);
}
static int MinDistance(int[] dist, int[] Blackened)
{
int min = INFINITY, min_index = -1, v;
for (v = 0; v < n; v++)
if (Blackened[v] == 0 && dist[v] < min)
{
min = dist[v];
min_index = v;
}
return min == INFINITY ? INFINITY : min_index;
}
// Function to print the path
static void PrintPath(int[] parent, int _d)
{
if (parent[_d] == NILL)
{
System.out.print(_d);
return;
}
PrintPath(parent, parent[_d]);
System.out.print("->" + _d);
}
// Driver Code
public static void main(String[] args)
{
// INFINITY means that u and v are not neighbors.
int[][] Graph = { { 0, 1, INFINITY, INFINITY, 10 },
{ 1, 0, 4, INFINITY, INFINITY },
{ INFINITY, 4, 0, 7, INFINITY },
{ INFINITY, INFINITY, 7, 0, 2 },
{ 10, INFINITY, INFINITY, 2, 0 } };
Dijkstra(Graph, n, s, d);
}
}
// This code is contributed by
// sanjeev2552
Python
# Python program to find the shortest path
# with minimum edges in a graph
def Dijkstra(Graph, _s, _d):
row = len(Graph)
col = len(Graph[0])
dist = [float("Inf")] * row
Blackened =[0] * row
pathlength =[0] * row
parent = [-1] * row
dist[_s]= 0
for count in range(row-1):
u = MinDistance(dist, Blackened)
# if MinDistance() returns INFINITY, then the graph is not
# connected and we have traversed all of the vertices in the
# connected component of the source vertex, so it can reduce
# the time complexity sometimes
# In a directed graph, it means that the source vertex
# is not a root
if u == float("Inf"):
break
else:
# Mark the vertex as Blackened
Blackened[u]= 1
for v in range(row):
if Blackened[v]== 0 and Graph[u][v] and dist[u]+Graph[u][v]", _d,
def MinDistance(dist, Blackened):
min = float("Inf")
for v in range(len(dist)):
if not Blackened[v] and dist[v]
0->4->3
时间复杂度: O(V^2),其中 V 是顶点数,E 是边数。
辅助空间: O(V + E)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。