ruta más larga en un gráfico acíclico dirigido | conjunto 2

Dado un gráfico acíclico dirigido ponderado (DAG) y un vértice de origen en él, encuentre las distancias más largas desde el vértice de origen hasta todos los demás vértices en el gráfico dado.

Ya hemos discutido cómo podemos encontrar la ruta más larga en el gráfico acíclico dirigido (DAG) en el Conjunto 1. En esta publicación, discutiremos otra solución interesante para encontrar la ruta más larga de DAG que usa un algoritmo para encontrar la ruta más corta en un DAG .

La idea es negar los pesos del camino y encontrar el camino más corto en el gráfico . Un camino más largo entre dos vértices dados s y t en un gráfico ponderado G es lo mismo que un camino más corto en un gráfico G’ derivado de G cambiando cada peso a su negación. Por lo tanto, si los caminos más cortos se pueden encontrar en G’, entonces los caminos más largos también se pueden encontrar en G. 
A continuación se muestra el proceso paso a paso para encontrar los caminos más largos:

Cambiamos el peso de cada borde del gráfico dado a su negación e inicializamos las distancias a todos los vértices como infinito y la distancia a la fuente como 0, luego encontramos una clasificación topológica del gráfico que representa un ordenamiento lineal del gráfico. Cuando consideramos un vértice u en orden topológico, se garantiza que hemos considerado todas las aristas entrantes. es decir, ya hemos encontrado la ruta más corta a ese vértice y podemos usar esa información para actualizar la ruta más corta de todos sus vértices adyacentes. Una vez que tenemos el orden topológico, procesamos uno por uno todos los vértices en orden topológico. Para cada vértice que se procesa, actualizamos las distancias de su vértice adyacente usando la distancia más corta del vértice actual desde el vértice de origen y su peso de borde. es decir 

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)

Una vez que hayamos encontrado todos los caminos más cortos desde el vértice de origen, los caminos más largos serán simplemente la negación de los caminos más cortos.

A continuación se muestra la implementación del enfoque anterior:

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.
// https://www.geeksforgeeks.org/topological-sorting/
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.
    // https://www.geeksforgeeks.org/topological-sorting/
    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.
Producción

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

Complejidad de tiempo : la complejidad de tiempo de la clasificación topológica es O (V + E). Después de encontrar el orden topológico, el algoritmo procesa todos los vértices y, para cada vértice, ejecuta un bucle para todos los vértices adyacentes. Como el total de vértices adyacentes en un gráfico es O(E), el ciclo interno se ejecuta O(V + E) veces. Por lo tanto, la complejidad temporal total de este algoritmo es O(V + E).

Este artículo es una contribución de Aditya Goel . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.org o enviar tu artículo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *