Given a Weighted Directed Acyclic Graph and a source vertex in the graph, find the shortest paths from given source to all other vertices.
For a general weighted graph, we can calculate single source shortest distances in O(VE) time using Bellman–Ford Algorithm. For a graph with no negative weights, we can do better and calculate single source shortest distances in O(E + VLogV) time using Dijkstra’s algorithm. Can we do even better for Directed Acyclic Graph (DAG)? We can calculate single source shortest distances in O(V+E) time for DAGs. The idea is to use Topological Sorting.
We initialize distances to all vertices as infinite and distance to source as 0, then we find a topological sorting of the graph. Topological Sorting of a graph represents a linear ordering of the graph (See below, figure (b) is a linear representation of figure (a) ). Once we have topological order (or linear representation), we one by one process all vertices in topological order. For every vertex being processed, we update distances of its adjacent using distance of current vertex.
Following figure is taken from this source. It shows step by step process of finding shortest paths.Â
Â
Â
Following is complete algorithm for finding shortest distances.Â
- Initialize dist[] = {INF, INF, ….} and dist[s] = 0 where s is the source vertex.Â
- Create a topological order of all vertices.Â
- Do following for every vertex u in topological order.Â
………..Do following for every adjacent vertex v of uÂ
………………if (dist[v] > dist[u] + weight(u, v))Â
………………………dist[v] = dist[u] + weight(u, v)Â
Â
Implementation:
C++
// C++ program to find single source shortest // paths for Directed Acyclic Graphs #include<iostream> #include <bits/stdc++.h> #define INF INT_MAX using namespace std; Â
// Graph is represented using adjacency list. Every node // of adjacency list contains vertex number of the vertex // to which edge connects. It also // contains weight of the edge class AdjListNode { Â Â Â Â int v; Â Â Â Â int weight; public : Â Â Â Â AdjListNode( int _v, int _w)Â { v = _v;Â weight = _w;} Â Â Â Â int getV()Â Â Â Â Â Â {Â return v;Â } Â Â Â Â int getWeight()Â {Â return weight; } }; Â
// Class to represent a graph using adjacency // list representation class Graph { Â Â Â Â int V;Â Â Â // No. of vertices' Â
    // Pointer to an array containing adjacency lists     list<AdjListNode> *adj; Â
    // A function used by shortestPath     void topologicalSortUtil( int v, bool visited[], stack< int > &Stack); public :     Graph( int V);  // Constructor Â
    // function to add an edge to graph     void addEdge( int u, int v, int weight); Â
    // Finds shortest paths from given source vertex     void shortestPath( int s); }; Â
Graph::Graph( int V) { Â Â Â Â this ->V = V; Â Â Â Â adj = new list<AdjListNode>[V]; } Â
void Graph::addEdge( int u, int v, int weight) { Â Â Â Â AdjListNode node(v, weight); Â Â Â Â adj[u].push_back(node); // Add v to u's list } Â
// A recursive function used by shortestPath. // See below link for details void Graph::topologicalSortUtil( int v, bool visited[], stack< int > &Stack) {     // Mark the current node as visited     visited[v] = true ; Â
    // Recur for all the vertices adjacent to this vertex     list<AdjListNode>::iterator i;     for (i = adj[v].begin(); i != adj[v].end(); ++i)     {         AdjListNode node = *i;         if (!visited[node.getV()])             topologicalSortUtil(node.getV(), visited, Stack);     } Â
    // Push current vertex to stack which stores topological sort     Stack.push(v); } Â
// The function to find shortest paths from given vertex. // It uses recursive topologicalSortUtil() to get topological // sorting of given graph. void Graph::shortestPath( int s) { Â Â Â Â stack< int > Stack; Â Â Â Â int dist[V]; Â
    // Mark all the vertices as not visited     bool *visited = new bool [V];     for ( int i = 0; i < V; i++)         visited[i] = false ; Â
    // Call the recursive helper function to store     // Topological Sort starting from all vertices     // one by one     for ( int i = 0; i < V; i++)         if (visited[i] == false )             topologicalSortUtil(i, visited, Stack); Â
    // Initialize distances to all vertices as     // infinite and distance to source as 0     for ( int i = 0; i < V; i++)         dist[i] = INF;     dist[s] = 0; Â
    // Process vertices in topological order     while (Stack.empty() == false )     {         // Get the next vertex from topological order         int u = Stack.top();         Stack.pop(); Â
        // Update distances of all adjacent vertices         list<AdjListNode>::iterator i;         if (dist[u] != INF)         {           for (i = adj[u].begin(); i != adj[u].end(); ++i)              if (dist[i->getV()] > dist[u] + i->getWeight())                 dist[i->getV()] = dist[u] + i->getWeight();         }     } Â
    // Print the calculated shortest distances     for ( int i = 0; i < V; i++)         (dist[i] == INF)? cout << "INF " : cout << dist[i] << " " ; } Â
// Driver program to test above functions int main() {     // Create a graph given in the above diagram.     // Here vertex numbers are 0, 1, 2, 3, 4, 5 with     // following mappings: 0=r, 1=s, 2=t, 3=x, 4=y, 5=z     Graph g(6);     g.addEdge(0, 1, 5);     g.addEdge(0, 2, 3);     g.addEdge(1, 3, 6);     g.addEdge(1, 2, 2);     g.addEdge(2, 4, 4);     g.addEdge(2, 5, 2);     g.addEdge(2, 3, 7);     g.addEdge(3, 4, -1);     g.addEdge(4, 5, -2); Â
    int s = 1;     cout << "Following are shortest distances from source " << s << " n" ;     g.shortestPath(s); Â
    return 0; } |
Java
// Java program to find single source shortest paths in Directed Acyclic Graphs import java.io.*; import java.util.*; Â
class ShortestPath {     static final int INF=Integer.MAX_VALUE;     class AdjListNode     {         private int v;         private int weight;         AdjListNode( int _v, int _w) { v = _v; weight = _w; }         int getV() { return v; }         int getWeight() { return weight; }     } Â
    // Class to represent graph as an adjacency list of     // nodes of type AdjListNode     class Graph     {         private int V;         private LinkedList<AdjListNode>adj[];         Graph( int v)         {             V=v;             adj = new LinkedList[V];             for ( int i= 0 ; i<v; ++i)                 adj[i] = new LinkedList<AdjListNode>();         }         void addEdge( int u, int v, int weight)         {             AdjListNode node = new AdjListNode(v,weight);             adj[u].add(node); // Add v to u's list         } Â
        // A recursive function used by shortestPath.         // See below link for details         void topologicalSortUtil( int v, Boolean visited[], Stack stack)         {             // Mark the current node as visited.             visited[v] = true ;             Integer i; Â
            // Recur for all the vertices adjacent to this vertex             Iterator<AdjListNode> it = adj[v].iterator();             while (it.hasNext())             {                 AdjListNode node =it.next();                 if (!visited[node.getV()])                     topologicalSortUtil(node.getV(), visited, stack);             }             // Push current vertex to stack which stores result             stack.push( new Integer(v));         } Â
        // The function to find shortest paths from given vertex. It         // uses recursive topologicalSortUtil() to get topological         // sorting of given graph.         void shortestPath( int s)         {             Stack stack = new Stack();             int dist[] = new int [V]; Â
            // Mark all the vertices as not visited             Boolean visited[] = new Boolean[V];             for ( int i = 0 ; i < V; i++)                 visited[i] = false ; Â
            // Call the recursive helper function to store Topological             // Sort starting from all vertices one by one             for ( int i = 0 ; i < V; i++)                 if (visited[i] == false )                     topologicalSortUtil(i, visited, stack); Â
            // Initialize distances to all vertices as infinite and             // distance to source as 0             for ( int i = 0 ; i < V; i++)                 dist[i] = INF;             dist[s] = 0 ; Â
            // Process vertices in topological order             while (stack.empty() == false )             {                 // Get the next vertex from topological order                 int u = ( int )stack.pop(); Â
                // Update distances of all adjacent vertices                 Iterator<AdjListNode> it;                 if (dist[u] != INF)                 {                     it = adj[u].iterator();                     while (it.hasNext())                     {                         AdjListNode i= it.next();                         if (dist[i.getV()] > dist[u] + i.getWeight())                             dist[i.getV()] = dist[u] + i.getWeight();                     }                 }             } Â
            // Print the calculated shortest distances             for ( int i = 0 ; i < V; i++)             {                 if (dist[i] == INF)                     System.out.print( "INF " );                 else                     System.out.print( dist[i] + " " );             }         }     } Â
    // Method to create a new graph instance through an object     // of ShortestPath class.     Graph newGraph( int number)     {         return new Graph(number);     } Â
    public static void main(String args[])     {         // Create a graph given in the above diagram. Here vertex         // numbers are 0, 1, 2, 3, 4, 5 with following mappings:         // 0=r, 1=s, 2=t, 3=x, 4=y, 5=z         ShortestPath t = new ShortestPath();         Graph g = t.newGraph( 6 );         g.addEdge( 0 , 1 , 5 );         g.addEdge( 0 , 2 , 3 );         g.addEdge( 1 , 3 , 6 );         g.addEdge( 1 , 2 , 2 );         g.addEdge( 2 , 4 , 4 );         g.addEdge( 2 , 5 , 2 );         g.addEdge( 2 , 3 , 7 );         g.addEdge( 3 , 4 , - 1 );         g.addEdge( 4 , 5 , - 2 ); Â
        int s = 1 ;         System.out.println( "Following are shortest distances " +                             "from source " + s );         g.shortestPath(s);     } } //This code is contributed by Aakash Hasija |
Python3
# Python program to find single source shortest paths # for Directed Acyclic Graphs Complexity :O(V+E) from collections import defaultdict Â
# Graph is represented using adjacency list. Every # node of adjacency list contains vertex number of # the vertex to which edge connects. It also contains # weight of the edge class Graph: Â Â Â Â def __init__( self ,vertices): Â
        self .V = vertices # No. of vertices Â
        # dictionary containing adjacency List         self .graph = defaultdict( list ) Â
    # function to add an edge to graph     def addEdge( self ,u,v,w):         self .graph[u].append((v,w)) Â
Â
    # A recursive function used by shortestPath     def topologicalSortUtil( self ,v,visited,stack): Â
        # Mark the current node as visited.         visited[v] = True Â
        # Recur for all the vertices adjacent to this vertex         if v in self .graph.keys():             for node,weight in self .graph[v]:                 if visited[node] = = False :                     self .topologicalSortUtil(node,visited,stack) Â
        # Push current vertex to stack which stores topological sort         stack.append(v) Â
Â
    ''' The function to find shortest paths from given vertex.         It uses recursive topologicalSortUtil() to get topological         sorting of given graph.'''     def shortestPath( self , s): Â
        # Mark all the vertices as not visited         visited = [ False ] * self .V         stack = [] Â
        # Call the recursive helper function to store Topological         # Sort starting from source vertices         for i in range ( self .V):             if visited[i] = = False :                 self .topologicalSortUtil(s,visited,stack) Â
        # Initialize distances to all vertices as infinite and         # distance to source as 0         dist = [ float ( "Inf" )] * ( self .V)         dist[s] = 0 Â
        # Process vertices in topological order         while stack: Â
            # Get the next vertex from topological order             i = stack.pop() Â
            # Update distances of all adjacent vertices             for node,weight in self .graph[i]:                 if dist[node] > dist[i] + weight:                     dist[node] = dist[i] + weight Â
        # Print the calculated shortest distances         for i in range ( self .V):             print (( "%d" % dist[i]) if dist[i] ! = float ( "Inf" ) else  "Inf" ,end = " " ) Â
Â
g = Graph( 6 ) g.addEdge( 0 , 1 , 5 ) g.addEdge( 0 , 2 , 3 ) g.addEdge( 1 , 3 , 6 ) g.addEdge( 1 , 2 , 2 ) g.addEdge( 2 , 4 , 4 ) g.addEdge( 2 , 5 , 2 ) g.addEdge( 2 , 3 , 7 ) g.addEdge( 3 , 4 , - 1 ) g.addEdge( 4 , 5 , - 2 ) Â
# source = 1 s = 1 Â
print ( "Following are shortest distances from source %d " % s) g.shortestPath(s) Â
# This code is contributed by Neelam Yadav |
C#
// C# program to find single source shortest // paths in Directed Acyclic Graphs using System; using System.Collections.Generic; Â
public class ShortestPath {     static readonly int INF = int .MaxValue;     class AdjListNode     {         public int v;         public int weight;         public AdjListNode( int _v, int _w) { v = _v; weight = _w; }         public int getV() { return v; }         public int getWeight() { return weight; }     } Â
    // Class to represent graph as an adjacency list of     // nodes of type AdjListNode     class Graph     {         public int V;         public List<AdjListNode>[]adj;         public Graph( int v)         {             V = v;             adj = new List<AdjListNode>[V];             for ( int i = 0; i < v; ++i)                 adj[i] = new List<AdjListNode>();         }         public void addEdge( int u, int v, int weight)         {             AdjListNode node = new AdjListNode(v,weight);             adj[u].Add(node); // Add v to u's list         } Â
        // A recursive function used by shortestPath.         // See below link for details         public void topologicalSortUtil( int v, Boolean []visited,                                         Stack< int > stack)         {             // Mark the current node as visited.             visited[v] = true ; Â
            // Recur for all the vertices adjacent to this vertex             foreach (AdjListNode it in adj[v])             {                 AdjListNode node = it;                 if (!visited[node.getV()])                     topologicalSortUtil(node.getV(), visited, stack);             }                          // Push current vertex to stack which stores result             stack.Push(v);         } Â
        // The function to find shortest paths from given vertex. It         // uses recursive topologicalSortUtil() to get topological         // sorting of given graph.         public void shortestPath( int s)         {             Stack< int > stack = new Stack< int >();             int []dist = new int [V]; Â
            // Mark all the vertices as not visited         Boolean []visited = new Boolean[V];             for ( int i = 0; i < V; i++)                 visited[i] = false ; Â
            // Call the recursive helper function to store Topological             // Sort starting from all vertices one by one             for ( int i = 0; i < V; i++)                 if (visited[i] == false )                     topologicalSortUtil(i, visited, stack); Â
            // Initialize distances to all vertices as infinite and             // distance to source as 0             for ( int i = 0; i < V; i++)                 dist[i] = INF;             dist[s] = 0; Â
            // Process vertices in topological order             while (stack.Count != 0)             {                 // Get the next vertex from topological order                 int u = ( int )stack.Pop(); Â
                // Update distances of all adjacent vertices                 if (dist[u] != INF)                 {                     foreach (AdjListNode it in adj[u])                     {                         AdjListNode i= it;                         if (dist[i.getV()] > dist[u] + i.getWeight())                             dist[i.getV()] = dist[u] + i.getWeight();                     }                 }             } Â
            // Print the calculated shortest distances             for ( int i = 0; i < V; i++)             {                 if (dist[i] == INF)                     Console.Write( "INF " );                 else                     Console.Write( dist[i] + " " );             }         }     } Â
    // Method to create a new graph instance through an object     // of ShortestPath class.     Graph newGraph( int number)     {         return new Graph(number);     } Â
    // Driver code     public static void Main(String []args)     {         // Create a graph given in the above diagram. Here vertex         // numbers are 0, 1, 2, 3, 4, 5 with following mappings:         // 0=r, 1=s, 2=t, 3=x, 4=y, 5=z         ShortestPath t = new ShortestPath();         Graph g = t.newGraph(6);         g.addEdge(0, 1, 5);         g.addEdge(0, 2, 3);         g.addEdge(1, 3, 6);         g.addEdge(1, 2, 2);         g.addEdge(2, 4, 4);         g.addEdge(2, 5, 2);         g.addEdge(2, 3, 7);         g.addEdge(3, 4, -1);         g.addEdge(4, 5, -2); Â
        int s = 1;         Console.WriteLine( "Following are shortest distances " +                             "from source " + s );         g.shortestPath(s);     } } Â
// This code is contributed by Rajput-Ji |
Javascript
// Javascript program to find single source shortest // paths for Directed Acyclic Graphs Â
      // program to implement stack data structure       class stack {         constructor() {           this .items = [];         } Â
        // add element to the stack         push(element) {           return this .items.push(element);         } Â
        // remove element from the stack         pop() {           if ( this .items.length > 0) {             return this .items.pop();           }         } Â
        // view the last element         top() {           return this .items[ this .items.length - 1];         } Â
        // check if the stack is empty         empty() {           return this .items.length == 0;         } Â
        // the size of the stack         size() {           return this .items.length;         } Â
        // empty the stack         clear() {           this .items = [];         }       } Â
      let INF = Number.MAX_VALUE; Â
      // Graph is represented using adjacency list. Every node       // of adjacency list contains vertex number of the vertex       // to which edge connects. It also       // contains weight of the edge       class AdjListNode {         constructor(_v, _w) {           this .v = _v;           this .weight = _w;         }         getV() {           return this .v;         }         getWeight() {           return this .weight;         }       } Â
      // Class to represent a graph using adjacency       // list representation       class Graph {         // Constructor         constructor(V) {           this .V = V; // No. of vertices'           // Pointer to an array containing adjacency lists           this .adj = Array.from(Array(V), () => new Array());         } Â
        // A function used by shortestPath         topologicalSortUtil(v, visited, Stack) {           // Mark the current node as visited           visited[v] = true ; Â
          // Recur for all the vertices adjacent to this vertex Â
          for (let j in this .adj[v]) {             let i = this .adj[v][j];             let node = i;             if (!visited[node.getV()])               this .topologicalSortUtil(node.getV(), visited, Stack);           } Â
          // Push current vertex to stack which stores topological           // sort           Stack.push(v);         } Â
        // function to add an edge to graph         addEdge(u, v, weight) {           let node = new AdjListNode(v, weight);           this .adj[u].push(node); // Add v to u's list         } Â
        // The function to find shortest paths from given vertex.         // It uses recursive topologicalSortUtil() to get topological         // sorting of given graph.         shortestPath(s) {           let Stack = new stack();           let dist = new Array( this .V); Â
          // Mark all the vertices as not visited           let visited = new Array( this .V);           for (let i = 0; i < this .V; i++) {             visited[i] = false ;           } Â
          // Call the recursive helper function to store Topological           // Sort starting from all vertices one by one           for (let i = 0; i < this .V; i++)             if (visited[i] == false )               this .topologicalSortUtil(i, visited, Stack); Â
          // Initialize distances to all vertices as infinite and           // distance to source as 0           for (let i = 0; i < this .V; i++) dist[i] = INF;           dist[s] = 0; Â
          // Process vertices in topological order           while (Stack.empty() == false ) {             // Get the next vertex from topological order             let u = Stack.top();             Stack.pop(); Â
            // Update distances of all adjacent vertices Â
            if (dist[u] != INF) {               for (let j in this .adj[u]) {                 let i = this .adj[u][j];                 if (dist[i.getV()] > dist[u] + i.getWeight())                   dist[i.getV()] = dist[u] + i.getWeight();               }             }           } Â
          // Print the calculated shortest distances           for (let i = 0; i < this .V; i++)             dist[i] == INF ? console.log( "INF " ) : console.log(dist[i] + " " );         }       } Â
      // Driver program to test above functions Â
      // Create a graph given in the above diagram.       // Here vertex numbers are 0, 1, 2, 3, 4, 5 with       // following mappings: 0=r, 1=s, 2=t, 3=x, 4=y, 5=z       let g = new Graph(6);       g.addEdge(0, 1, 5);       g.addEdge(0, 2, 3);       g.addEdge(1, 3, 6);       g.addEdge(1, 2, 2);       g.addEdge(2, 4, 4);       g.addEdge(2, 5, 2);       g.addEdge(2, 3, 7);       g.addEdge(3, 4, -1);       g.addEdge(4, 5, -2); Â
      let s = 1;       console.log( "Following are shortest distances from source " + s);       g.shortestPath(s);              // This code is contributed by satwiksuman. |
Following are shortest distances from source 1 nINF 0 2 6 5 3
Time Complexity: Time complexity of topological sorting is O(V+E). After finding topological order, the algorithm process all vertices and for every vertex, it runs a loop for all adjacent vertices. Total adjacent vertices in a graph is O(E). So the inner loop runs O(V+E) times. Therefore, overall time complexity of this algorithm is O(V+E).
Auxiliary Space : O(V+E)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!