给定一个有向图和图中的一个源顶点,任务是在给定的图中找到从源到目标顶点的最短距离和路径,其中边被加权(非负)并且从父顶点指向源顶点。
方法:
- 标记所有未访问的顶点。创建一组所有未访问的顶点。
- 将零距离值分配给源顶点,将无穷远距离值分配给所有其他顶点。
- 将源顶点设置为当前顶点
- 对于当前顶点,考虑其所有未访问的子节点并计算它们通过当前的暂定距离。 (当前距离+对应边的权重)将新计算的距离与当前分配的值(对于某些顶点可以是无穷大)进行比较并分配较小的。
- 在考虑当前顶点的所有未访问子节点后,将当前标记为已访问并将其从未访问集中删除。
- 类似地,对所有顶点继续,直到所有节点都被访问。
下面是上述方法的实现:
C++
// C++ implementation to find the
// shortest path in a directed
// graph from source vertex to
// the destination vertex
#include
#define infi 1000000000
using namespace std;
// Class of the node
class Node {
public:
int vertexNumber;
// Adjacency list that shows the
// vertexNumber of child vertex
// and the weight of the edge
vector > children;
Node(int vertexNumber)
{
this->vertexNumber = vertexNumber;
}
// Function to add the child for
// the given node
void add_child(int vNumber, int length)
{
pair p;
p.first = vNumber;
p.second = length;
children.push_back(p);
}
};
// Function to find the distance of
// the node from the given source
// vertex to the destination vertex
vector dijkstraDist(
vector g,
int s, vector& path)
{
// Stores distance of each
// vertex from source vertex
vector dist(g.size());
// Boolean array that shows
// whether the vertex 'i'
// is visited or not
bool visited[g.size()];
for (int i = 0; i < g.size(); i++) {
visited[i] = false;
path[i] = -1;
dist[i] = infi;
}
dist[s] = 0;
path[s] = -1;
int current = s;
// Set of vertices that has
// a parent (one or more)
// marked as visited
unordered_set sett;
while (true) {
// Mark current as visited
visited[current] = true;
for (int i = 0;
i < g[current]->children.size();
i++) {
int v = g[current]->children[i].first;
if (visited[v])
continue;
// Inserting into the
// visited vertex
sett.insert(v);
int alt
= dist[current]
+ g[current]->children[i].second;
// Condition to check the distance
// is correct and update it
// if it is minimum from the previous
// computed distance
if (alt < dist[v]) {
dist[v] = alt;
path[v] = current;
}
}
sett.erase(current);
if (sett.empty())
break;
// The new current
int minDist = infi;
int index = 0;
// Loop to update the distance
// of the vertices of the graph
for (int a: sett) {
if (dist[a] < minDist) {
minDist = dist[a];
index = a;
}
}
current = index;
}
return dist;
}
// Function to print the path
// from the source vertex to
// the destination vertex
void printPath(vector path,
int i, int s)
{
if (i != s) {
// Condition to check if
// there is no path between
// the vertices
if (path[i] == -1) {
cout << "Path not found!!";
return;
}
printPath(path, path[i], s);
cout << path[i] << " ";
}
}
// Driver Code
int main()
{
vector v;
int n = 4, s = 0, e = 5;
// Loop to create the nodes
for (int i = 0; i < n; i++) {
Node* a = new Node(i);
v.push_back(a);
}
// Creating directed
// weighted edges
v[0]->add_child(1, 1);
v[0]->add_child(2, 4);
v[1]->add_child(2, 2);
v[1]->add_child(3, 6);
v[2]->add_child(3, 3);
vector path(v.size());
vector dist
= dijkstraDist(v, s, path);
// Loop to print the distance of
// every node from source vertex
for (int i = 0; i < dist.size(); i++) {
if (dist[i] == infi) {
cout << i << " and " << s
<< " are not connected"
<< endl;
continue;
}
cout << "Distance of " << i
<< "th vertex from source vertex "
<< s << " is: "
<< dist[i] << endl;
}
return 0;
}
Java
// Java implementation to find the
// shortest path in a directed
// graph from source vertex to
// the destination vertex
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
class Pair
{
int first, second;
public Pair(int first, int second)
{
this.first = first;
this.second = second;
}
}
class GFG{
static final int infi = 1000000000;
// Class of the node
static class Node
{
int vertexNumber;
// Adjacency list that shows the
// vertexNumber of child vertex
// and the weight of the edge
List children;
Node(int vertexNumber)
{
this.vertexNumber = vertexNumber;
children = new ArrayList<>();
}
// Function to add the child for
// the given node
void add_child(int vNumber, int length)
{
Pair p = new Pair(vNumber, length);
children.add(p);
}
}
// Function to find the distance of
// the node from the given source
// vertex to the destination vertex
static int[] dijkstraDist(List g,
int s, int[] path)
{
// Stores distance of each
// vertex from source vertex
int[] dist = new int[g.size()];
// Boolean array that shows
// whether the vertex 'i'
// is visited or not
boolean[] visited = new boolean[g.size()];
for(int i = 0; i < g.size(); i++)
{
visited[i] = false;
path[i] = -1;
dist[i] = infi;
}
dist[s] = 0;
path[s] = -1;
int current = s;
// Set of vertices that has
// a parent (one or more)
// marked as visited
Set sett = new HashSet<>();
while (true)
{
// Mark current as visited
visited[current] = true;
for(int i = 0;
i < g.get(current).children.size();
i++)
{
int v = g.get(current).children.get(i).first;
if (visited[v])
continue;
// Inserting into the
// visited vertex
sett.add(v);
int alt = dist[current] +
g.get(current).children.get(i).second;
// Condition to check the distance
// is correct and update it
// if it is minimum from the previous
// computed distance
if (alt < dist[v])
{
dist[v] = alt;
path[v] = current;
}
}
sett.remove(current);
if (sett.isEmpty())
break;
// The new current
int minDist = infi;
int index = 0;
// Loop to update the distance
// of the vertices of the graph
for(int a : sett)
{
if (dist[a] < minDist)
{
minDist = dist[a];
index = a;
}
}
current = index;
}
return dist;
}
// Function to print the path
// from the source vertex to
// the destination vertex
void printPath(int[] path, int i, int s)
{
if (i != s)
{
// Condition to check if
// there is no path between
// the vertices
if (path[i] == -1)
{
System.out.println("Path not found!!");
return;
}
printPath(path, path[i], s);
System.out.print(path[i] + " ");
}
}
// Driver Code
public static void main(String[] args)
{
List v = new ArrayList<>();
int n = 4, s = 0, e = 5;
// Loop to create the nodes
for(int i = 0; i < n; i++)
{
Node a = new Node(i);
v.add(a);
}
// Creating directed
// weighted edges
v.get(0).add_child(1, 1);
v.get(0).add_child(2, 4);
v.get(1).add_child(2, 2);
v.get(1).add_child(3, 6);
v.get(2).add_child(3, 3);
int[] path = new int[v.size()];
int[] dist = dijkstraDist(v, s, path);
// Loop to print the distance of
// every node from source vertex
for(int i = 0; i < dist.length; i++)
{
if (dist[i] == infi)
{
System.out.printf("%d and %d are not " +
"connected\n", i, s);
continue;
}
System.out.printf("Distance of %dth vertex " +
"from source vertex %d is: %d\n",
i, s, dist[i]);
}
}
}
// This code is contributed by sanjeev2552
Python3
# Python3 implementation to find the
# shortest path in a directed
# graph from source vertex to
# the destination vertex
class Pair:
def __init__(self, first, second):
self.first = first
self.second = second
infi = 1000000000;
# Class of the node
class Node:
# Adjacency list that shows the
# vertexNumber of child vertex
# and the weight of the edge
def __init__(self, vertexNumber):
self.vertexNumber = vertexNumber
self.children = []
# Function to add the child for
# the given node
def Add_child(self, vNumber, length):
p = Pair(vNumber, length);
self.children.append(p);
# Function to find the distance of
# the node from the given source
# vertex to the destination vertex
def dijkstraDist(g, s, path):
# Stores distance of each
# vertex from source vertex
dist = [infi for i in range(len(g))]
# bool array that shows
# whether the vertex 'i'
# is visited or not
visited = [False for i in range(len(g))]
for i in range(len(g)):
path[i] = -1
dist[s] = 0;
path[s] = -1;
current = s;
# Set of vertices that has
# a parent (one or more)
# marked as visited
sett = set()
while (True):
# Mark current as visited
visited[current] = True;
for i in range(len(g[current].children)):
v = g[current].children[i].first;
if (visited[v]):
continue;
# Inserting into the
# visited vertex
sett.add(v);
alt = dist[current] + g[current].children[i].second;
# Condition to check the distance
# is correct and update it
# if it is minimum from the previous
# computed distance
if (alt < dist[v]):
dist[v] = alt;
path[v] = current;
if current in sett:
sett.remove(current);
if (len(sett) == 0):
break;
# The new current
minDist = infi;
index = 0;
# Loop to update the distance
# of the vertices of the graph
for a in sett:
if (dist[a] < minDist):
minDist = dist[a];
index = a;
current = index;
return dist;
# Function to print the path
# from the source vertex to
# the destination vertex
def printPath(path, i, s):
if (i != s):
# Condition to check if
# there is no path between
# the vertices
if (path[i] == -1):
print("Path not found!!");
return;
printPath(path, path[i], s);
print(path[i] + " ");
# Driver Code
if __name__=='__main__':
v = []
n = 4
s = 0;
# Loop to create the nodes
for i in range(n):
a = Node(i);
v.append(a);
# Creating directed
# weighted edges
v[0].Add_child(1, 1);
v[0].Add_child(2, 4);
v[1].Add_child(2, 2);
v[1].Add_child(3, 6);
v[2].Add_child(3, 3);
path = [0 for i in range(len(v))];
dist = dijkstraDist(v, s, path);
# Loop to print the distance of
# every node from source vertex
for i in range(len(dist)):
if (dist[i] == infi):
print("{0} and {1} are not " +
"connected".format(i, s));
continue;
print("Distance of {}th vertex from source vertex {} is: {}".format(
i, s, dist[i]));
# This code is contributed by pratham76
C#
// C# implementation to find the
// shortest path in a directed
// graph from source vertex to
// the destination vertex
using System;
using System.Collections;
using System.Collections.Generic;
class Pair
{
public int first, second;
public Pair(int first, int second)
{
this.first = first;
this.second = second;
}
}
class GFG
{
static int infi = 1000000000;
// Class of the node
class Node
{
public int vertexNumber;
// Adjacency list that shows the
// vertexNumber of child vertex
// and the weight of the edge
public List children;
public Node(int vertexNumber)
{
this.vertexNumber = vertexNumber;
children = new List();
}
// Function to Add the child for
// the given node
public void Add_child(int vNumber, int length)
{
Pair p = new Pair(vNumber, length);
children.Add(p);
}
}
// Function to find the distance of
// the node from the given source
// vertex to the destination vertex
static int[] dijkstraDist(List g,
int s, int[] path)
{
// Stores distance of each
// vertex from source vertex
int[] dist = new int[g.Count];
// bool array that shows
// whether the vertex 'i'
// is visited or not
bool[] visited = new bool[g.Count];
for(int i = 0; i < g.Count; i++)
{
visited[i] = false;
path[i] = -1;
dist[i] = infi;
}
dist[s] = 0;
path[s] = -1;
int current = s;
// Set of vertices that has
// a parent (one or more)
// marked as visited
HashSet sett = new HashSet();
while (true)
{
// Mark current as visited
visited[current] = true;
for(int i = 0;
i < g[current].children.Count;
i++)
{
int v = g[current].children[i].first;
if (visited[v])
continue;
// Inserting into the
// visited vertex
sett.Add(v);
int alt = dist[current] +
g[current].children[i].second;
// Condition to check the distance
// is correct and update it
// if it is minimum from the previous
// computed distance
if (alt < dist[v])
{
dist[v] = alt;
path[v] = current;
}
}
sett.Remove(current);
if (sett.Count == 0)
break;
// The new current
int minDist = infi;
int index = 0;
// Loop to update the distance
// of the vertices of the graph
foreach(int a in sett)
{
if (dist[a] < minDist)
{
minDist = dist[a];
index = a;
}
}
current = index;
}
return dist;
}
// Function to print the path
// from the source vertex to
// the destination vertex
void printPath(int[] path, int i, int s)
{
if (i != s)
{
// Condition to check if
// there is no path between
// the vertices
if (path[i] == -1)
{
Console.WriteLine("Path not found!!");
return;
}
printPath(path, path[i], s);
Console.WriteLine(path[i] + " ");
}
}
// Driver Code
public static void Main(string[] args)
{
List v = new List();
int n = 4, s = 0;
// Loop to create the nodes
for(int i = 0; i < n; i++)
{
Node a = new Node(i);
v.Add(a);
}
// Creating directed
// weighted edges
v[0].Add_child(1, 1);
v[0].Add_child(2, 4);
v[1].Add_child(2, 2);
v[1].Add_child(3, 6);
v[2].Add_child(3, 3);
int[] path = new int[v.Count];
int[] dist = dijkstraDist(v, s, path);
// Loop to print the distance of
// every node from source vertex
for(int i = 0; i < dist.Length; i++)
{
if (dist[i] == infi)
{
Console.Write("{0} and {1} are not " +
"connected\n", i, s);
continue;
}
Console.Write("Distance of {0}th vertex " +
"from source vertex {1} is: {2}\n",
i, s, dist[i]);
}
}
}
// This code is contributed by rutvik_56
输出:
第 0 个顶点与源顶点 0 的距离为:0
第 1 个顶点与源顶点 0 的距离为:1
第 2 个顶点与源顶点 0 的距离为:3
第 3 个顶点与源顶点 0 的距离为:6
第 0 个顶点与源顶点 0 的距离为:0
第 1 个顶点与源顶点 0 的距离为:1
第 2 个顶点与源顶点 0 的距离为:3
第 3 个顶点与源顶点 0 的距离为:6
时间复杂度:
辅助空间: O(V + E)
相关文章:我们已经讨论了使用拓扑排序的有向图中的最短路径,在这篇文章中:有向无环图中的最短路径