Dado un gráfico dirigido y un vértice de origen en el gráfico, la tarea es encontrar la distancia y la ruta más cortas desde el origen hasta el vértice de destino en el gráfico dado donde los bordes se ponderan (no son negativos) y se dirigen desde el vértice principal hasta los vértices de origen.
Acercarse:
- Marque todos los vértices sin visitar. Crea un conjunto de todos los vértices no visitados.
- Asigne un valor de distancia cero al vértice de origen y un valor de distancia infinito a todos los demás vértices.
- Establecer el vértice de origen como vértice actual
- Para el vértice actual, considere todos sus hijos no visitados y calcule sus distancias tentativas a través de la corriente. (distancia de la corriente + peso del borde correspondiente) Compare la distancia recién calculada con el valor asignado actual (puede ser infinito para algunos vértices) y asigne la más pequeña.
- Después de considerar todos los hijos no visitados del vértice actual, marque el actual como visitado y elimínelo del conjunto no visitado.
- Del mismo modo, continúe por todos los vértices hasta que se visiten todos los Nodes.
A continuación se muestra la implementación del enfoque anterior:
C++
// C++ implementation to find the // shortest path in a directed // graph from source vertex to // the destination vertex #include <bits/stdc++.h> #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<pair<int, int> > children; Node(int vertexNumber) { this->vertexNumber = vertexNumber; } // Function to add the child for // the given node void add_child(int vNumber, int length) { pair<int, int> 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<int> dijkstraDist( vector<Node*> g, int s, vector<int>& path) { // Stores distance of each // vertex from source vertex vector<int> 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<int> 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<int> 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<Node*> 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<int> path(v.size()); vector<int> 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<Pair> 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<Node> 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<Integer> 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<Node> 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<Pair> children; public Node(int vertexNumber) { this.vertexNumber = vertexNumber; children = new List<Pair>(); } // 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<Node> 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<int> sett = new HashSet<int>(); 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<Node> v = new List<Node>(); 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
Salida: La
distancia del vértice 0 desde el vértice de origen 0 es: 0 La
distancia del vértice 1 desde el vértice de origen 0 es: 1 La
distancia del vértice 2 desde el vértice de origen 0 es: 3
La distancia del vértice 3 desde el vértice de origen 0 es: 6
distancia del vértice 0 desde el vértice de origen 0 es: 0 La
distancia del vértice 1 desde el vértice de origen 0 es: 1 La
distancia del vértice 2 desde el vértice de origen 0 es: 3
La distancia del vértice 3 desde el vértice de origen 0 es: 6
Complejidad de tiempo:
Espacio auxiliar: O(V + E)
Artículos relacionados: Ya hemos discutido la ruta más corta en un gráfico dirigido utilizando Clasificación topológica, en este artículo: Ruta más corta en un gráfico acíclico dirigido