Open In App

Longest Path in a Directed Acyclic Graph | Set 2

Last Updated : 13 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a Weighted Directed Acyclic Graph (DAG) and a source vertex in it, find the longest distances from source vertex to all other vertices in the given graph.

We have already discussed how we can find Longest Path in Directed Acyclic Graph(DAG) in Set 1. In this post, we will discuss another interesting solution to find longest path of DAG that uses algorithm for finding Shortest Path in a DAG.

The idea is to negate the weights of the path and find the shortest path in the graph. A longest path between two given vertices s and t in a weighted graph G is the same thing as a shortest path in a graph G’ derived from G by changing every weight to its negation. Therefore, if shortest paths can be found in G’, then longest paths can also be found in G. 
Below is the step by step process of finding longest paths –

We change weight of every edge of given graph to its negation and initialize distances to all vertices as infinite and distance to source as 0, then we find a topological sorting of the graph which represents a linear ordering of the graph. When we consider a vertex u in topological order, it is guaranteed that we have considered every incoming edge to it. i.e. We have already found shortest path to that vertex and we can use that info to update shorter path of all its adjacent vertices. Once we have topological order, we one by one process all vertices in topological order. For every vertex being processed, we update distances of its adjacent vertex using shortest distance of current vertex from source vertex and its edge weight. i.e. 

for every adjacent vertex v of every vertex u in topological order
    if (dist[v] > dist[u] + weight(u, v))
    dist[v] = dist[u] + weight(u, v)

Once we have found all shortest paths from the source vertex, longest paths will be just negation of shortest paths.

Below is the implementation of the above approach:

C++




// A C++ program to find single source longest distances
// in a DAG
#include <bits/stdc++.h>
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;
    }
};
 
// Graph class represents a directed graph using adjacency
// list representation
class Graph
{
    int V; // No. of vertices
 
    // Pointer to an array containing adjacency lists
    list<AdjListNode>* adj;
 
    // This function uses DFS
    void longestPathUtil(int, vector<bool> &, stack<int> &);
public:
    Graph(int); // Constructor
    ~Graph();   // Destructor
 
    // function to add an edge to graph
    void addEdge(int, int, int);
 
    void longestPath(int);
};
 
Graph::Graph(int V) // Constructor
{
    this->V = V;
    adj = new list<AdjListNode>[V];
}
 
Graph::~Graph() // Destructor
{
    delete[] adj;
}
 
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 longestPath. See below
// link for details.
void Graph::longestPathUtil(int v, vector<bool> &visited,
                            stack<int> &Stack)
{
    // Mark the current node as visited
    visited[v] = true;
 
    // Recur for all the vertices adjacent to this vertex
    for (AdjListNode node : adj[v])
    {
        if (!visited[node.getV()])
            longestPathUtil(node.getV(), visited, Stack);
    }
 
    // Push current vertex to stack which stores topological
    // sort
    Stack.push(v);
}
 
// The function do Topological Sort and finds longest
// distances from given source vertex
void Graph::longestPath(int s)
{
    // Initialize distances to all vertices as infinite and
    // distance to source as 0
    int dist[V];
    for (int i = 0; i < V; i++)
        dist[i] = INT_MAX;
    dist[s] = 0;
 
    stack<int> Stack;
 
    // Mark all the vertices as not visited
    vector<bool> visited(V, false);
 
    for (int i = 0; i < V; i++)
        if (visited[i] == false)
            longestPathUtil(i, visited, Stack);
 
    // Process vertices in topological order
    while (!Stack.empty())
    {
        // Get the next vertex from topological order
        int u = Stack.top();
        Stack.pop();
 
        if (dist[u] != INT_MAX)
        {
            // Update distances of all adjacent vertices
            // (edge from u -> v exists)
            for (AdjListNode v : adj[u])
            {
                // consider negative weight of edges and
                // find shortest path
                if (dist[v.getV()] > dist[u] + v.getWeight() * -1)
                    dist[v.getV()] = dist[u] + v.getWeight() * -1;
            }
        }
    }
 
    // Print the calculated longest distances
    for (int i = 0; i < V; i++)
    {
        if (dist[i] == INT_MAX)
            cout << "INT_MIN ";
        else
            cout << (dist[i] * -1) << " ";
    }
}
 
// Driver code
int main()
{
    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, 5, 1);
    g.addEdge(3, 4, -1);
    g.addEdge(4, 5, -2);
 
    int s = 1;
 
    cout << "Following are longest distances from "
         << "source vertex " << s << " \n";
    g.longestPath(s);
 
    return 0;
}


Python3




# A Python3 program to find single source
# longest distances in a DAG
import sys
 
def addEdge(u, v, w):
     
    global adj
    adj[u].append([v, w])
 
# A recursive function used by longestPath.
# See below link for details.
# https:#www.geeksforgeeks.org/topological-sorting/
def longestPathUtil(v):
     
    global visited, adj,Stack
    visited[v] = 1
 
    # Recur for all the vertices adjacent
    # to this vertex
    for node in adj[v]:
        if (not visited[node[0]]):
            longestPathUtil(node[0])
 
    # Push current vertex to stack which
    # stores topological sort
    Stack.append(v)
 
# The function do Topological Sort and finds
# longest distances from given source vertex
def longestPath(s):
     
    # Initialize distances to all vertices
    # as infinite and
    global visited, Stack, adj,V
    dist = [sys.maxsize for i in range(V)]
    # for (i = 0 i < V i++)
    #     dist[i] = INT_MAX
    dist[s] = 0
 
    for i in range(V):
        if (visited[i] == 0):
            longestPathUtil(i)
 
    # print(Stack)
    while (len(Stack) > 0):
         
        # Get the next vertex from topological order
        u = Stack[-1]
        del Stack[-1]
 
        if (dist[u] != sys.maxsize):
             
            # Update distances of all adjacent vertices
            # (edge from u -> v exists)
            for v in adj[u]:
                 
                # Consider negative weight of edges and
                # find shortest path
                if (dist[v[0]] > dist[u] + v[1] * -1):
                    dist[v[0]] = dist[u] + v[1] * -1
 
    # Print the calculated longest distances
    for i in range(V):
        if (dist[i] == sys.maxsize):
            print("INT_MIN ", end = " ")
        else:
            print(dist[i] * (-1), end = " ")
 
# Driver code
if __name__ == '__main__':
     
    V = 6
    visited = [0 for i in range(7)]
    Stack = []
    adj = [[] for i in range(7)]
 
    addEdge(0, 1, 5)
    addEdge(0, 2, 3)
    addEdge(1, 3, 6)
    addEdge(1, 2, 2)
    addEdge(2, 4, 4)
    addEdge(2, 5, 2)
    addEdge(2, 3, 7)
    addEdge(3, 5, 1)
    addEdge(3, 4, -1)
    addEdge(4, 5, -2)
 
    s = 1
 
    print("Following are longest distances from source vertex", s)
     
    longestPath(s)
 
# This code is contributed by mohit kumar 29


C#




// C# program to find single source longest distances
// in a DAG
using System;
using System.Collections.Generic;
 
// 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 {
    private int v;
    private int weight;
 
    public AdjListNode(int _v, int _w)
    {
        v = _v;
        weight = _w;
    }
    public int getV() { return v; }
    public int getWeight() { return weight; }
}
 
// Graph class represents a directed graph using adjacency
// list representation
class Graph {
    private int V; // No. of vertices
 
    // Pointer to an array containing adjacency lists
    private List<AdjListNode>[] adj;
 
    public Graph(int v) // Constructor
    {
        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 longestPath. See below
    // link for details.
    private void LongestPathUtil(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
        foreach(AdjListNode node in adj[v])
        {
            if (!visited[node.getV()])
                LongestPathUtil(node.getV(), visited,
                                stack);
        }
 
        // Push current vertex to stack which stores
        // topological sort
        stack.Push(v);
    }
 
    // The function do Topological Sort and finds longest
    // distances from given source vertex
    public void LongestPath(int s)
    {
       
        // Initialize distances to all vertices as infinite
        // and distance to source as 0
        int[] dist = new int[V];
        for (int i = 0; i < V; i++)
            dist[i] = Int32.MaxValue;
        dist[s] = 0;
 
        Stack<int> stack = new Stack<int>();
 
        // Mark all the vertices as not visited
        bool[] visited = new bool[V];
 
        for (int i = 0; i < V; i++) {
            if (visited[i] == false)
                LongestPathUtil(i, visited, stack);
        }
 
        // Process vertices in topological order
        while (stack.Count > 0) {
            // Get the next vertex from topological order
            int u = stack.Pop();
 
            if (dist[u] != Int32.MaxValue) {
                // Update distances of all adjacent vertices
                // (edge from u -> v exists)
                foreach(AdjListNode v in adj[u])
                {
                    // consider negative weight of edges and
                    // find shortest path
                    if (dist[v.getV()]
                        > dist[u] + v.getWeight() * -1)
                        dist[v.getV()]
                            = dist[u] + v.getWeight() * -1;
                }
            }
        }
 
        // Print the calculated longest distances
        for (int i = 0; i < V; i++) {
            if (dist[i] == Int32.MaxValue)
                Console.Write("INT_MIN ");
            else
                Console.Write("{0} ", dist[i] * -1);
        }
        Console.WriteLine();
    }
}
 
public class GFG {
    // Driver code
    static void Main(string[] args)
    {
        Graph 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, 5, 1);
        g.AddEdge(3, 4, -1);
        g.AddEdge(4, 5, -2);
 
        int s = 1;
 
        Console.WriteLine(
            "Following are longest distances from source vertex {0} ",
            s);
        g.LongestPath(s);
    }
}
 
// This code is contributed by cavi4762.


Java




// A Java program to find single source longest distances
// in a DAG
import java.util.*;
 
// 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 {
    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 a graph using adjacency list
// representation
public class GFG {
    int V; // No. of vertices'
 
    // Pointer to an array containing adjacency lists
    ArrayList<AdjListNode>[] adj;
    @SuppressWarnings("unchecked")
 
    GFG(int V) // Constructor
    {
        this.V = V;
        adj = new ArrayList[V];
        for (int i = 0; i < V; i++) {
            adj[i] = new ArrayList<>();
        }
    }
 
    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 longestPath. See
    // below link for details https://
    // www.geeksforgeeks.org/topological-sorting/
    void topologicalSortUtil(int v, boolean visited[],
                             Stack<Integer> stack)
    {
        // Mark the current node as visited
        visited[v] = true;
 
        // Recur for all the vertices adjacent to this
        // vertex
        for (int i = 0; i < adj[v].size(); i++) {
            AdjListNode node = adj[v].get(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 Smallest distances from a
    // given vertex. It uses recursive
    // topologicalSortUtil() to get topological sorting.
    void longestPath(int s)
    {
        Stack<Integer> stack = new Stack<Integer>();
        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] = Integer.MAX_VALUE;
 
        dist[s] = 0;
 
        // Process vertices in topological order
        while (stack.isEmpty() == false) {
 
            // Get the next vertex from topological
            // order
            int u = stack.peek();
            stack.pop();
 
            // Update distances of all adjacent vertices
            if (dist[u] != Integer.MAX_VALUE) {
                for (AdjListNode v : adj[u]) {
                    if (dist[v.getV()]
                        > dist[u] + v.getWeight() * -1)
                        dist[v.getV()]
                            = dist[u] + v.getWeight() * -1;
                }
            }
        }
 
        // Print the calculated longest distances
        for (int i = 0; i < V; i++)
            if (dist[i] == Integer.MAX_VALUE)
                System.out.print("INF ");
            else
                System.out.print(dist[i] * -1 + " ");
    }
 
    // Driver program to test above functions
    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
        GFG g = new GFG(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, 5, 1);
        g.addEdge(3, 4, -1);
        g.addEdge(4, 5, -2);
 
        int s = 1;
        System.out.print(
            "Following are longest distances from source vertex "
            + s + " \n");
        g.longestPath(s);
    }
}
// This code is contributed by Prithi_Dey


Javascript




class AdjListNode {
    constructor(v, weight) {
        this.v = v;
        this.weight = weight;
    }
    getV() { return this.v; }
    getWeight() { return this.weight; }
}
 
class GFG {
    constructor(V) {
        this.V = V;
        this.adj = new Array(V);
        for (let i = 0; i < V; i++) {
            this.adj[i] = new Array();
        }
    }
    addEdge(u, v, weight) {
        let node = new AdjListNode(v, weight);
        this.adj[u].push(node);
    }
    topologicalSortUtil(v, visited, stack) {
        visited[v] = true;
        for (let i = 0; i < this.adj[v].length; i++) {
            let node = this.adj[v][i];
            if (!visited[node.getV()]) {
                this.topologicalSortUtil(node.getV(), visited, stack);
            }
        }
        stack.push(v);
    }
    longestPath(s) {
        let stack = new Array();
        let dist = new Array(this.V);
        let visited = new Array(this.V);
        for (let i = 0; i < this.V; i++) {
            visited[i] = false;
        }
        for (let i = 0; i < this.V; i++) {
            if (!visited[i]) {
                this.topologicalSortUtil(i, visited, stack);
            }
        }
        for (let i = 0; i < this.V; i++) {
            dist[i] = Number.MAX_SAFE_INTEGER;
        }
         
         
        dist[s] = 0;
       let u = stack.pop();
       while (stack.length > 0) {
       u = stack.pop();
       if (dist[u] !== Number.MAX_SAFE_INTEGER) {
        for (let v of this.adj[u]) {
            if (dist[v.getV()] > dist[u] + v.getWeight() * -1) {
                dist[v.getV()] = dist[u] + v.getWeight() * -1;
            }
        }
    }
}
 
         
         
        for (let i = 0; i < this.V; i++) {
            if (dist[i] === Number.MAX_SAFE_INTEGER) {
                console.log("INF");
            }
            else {
                console.log(dist[i] * -1);
            }
        }
    }
}
let g = new GFG(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, 5, 1);
g.addEdge(3, 4, -1);
g.addEdge(4, 5, -2);
 
console.log("Longest distances from the vertex 1 : ");
g.longestPath(1);
//this code is contributed by devendra


Output

Following are longest distances from source vertex 1 
INT_MIN 0 2 9 8 10 

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. As total adjacent vertices in a graph is O(E), the inner loop runs O(V + E) times. Therefore, overall time complexity of this algorithm is O(V + E).

Space Complexity:
The space complexity of the above algorithm is O(V). We are storing the output array and a stack for topological sorting.



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads