logo

Cea mai lungă cale într-un grafic aciclic direcționat | Setul 2

Având în vedere un grafic aciclic direcționat ponderat (DAG) și un vârf sursă din acesta, găsiți cele mai mari distanțe de la vârful sursă la toate celelalte vârfuri din graficul dat.

Am discutat deja cum putem găsi Cea mai lungă cale în graficul aciclic direcționat (DAG) în setul 1. În această postare vom discuta o altă soluție interesantă pentru a găsi cea mai lungă cale a DAG care utilizează algoritmul pentru găsirea Cea mai scurtă cale într-un DAG .



Ideea este să anulați greutățile căii și găsiți calea cea mai scurtă din grafic . O cale cea mai lungă între două vârfuri date s și t într-un grafic ponderat G este același lucru cu o cale cea mai scurtă dintr-un grafic G' derivat din G prin schimbarea fiecărei ponderi la negația sa. Prin urmare, dacă cele mai scurte căi pot fi găsite în G', atunci cele mai lungi căi pot fi găsite și în G. 
Mai jos este procesul pas cu pas pentru găsirea celor mai lungi căi -

Schimbăm ponderea fiecărei margini a graficului dat la negația sa și inițializam distanțele la toate vârfurile ca infinite și distanța la sursă ca 0, apoi găsim o sortare topologică a graficului care reprezintă o ordonare liniară a graficului. Când luăm în considerare un vârf u în ordine topologică, este garantat că am luat în considerare fiecare muchie de intrare a acestuia. adică am găsit deja cea mai scurtă cale către acel vârf și putem folosi aceste informații pentru a actualiza calea mai scurtă a tuturor vârfurilor adiacente. Odată ce avem ordinea topologică, procesăm unul câte unul toate vârfurile în ordine topologică. Pentru fiecare vârf procesat, actualizăm distanțele vârfului său adiacent utilizând cea mai scurtă distanță a vârfului curent de la vârful sursă și greutatea marginii acestuia. adică 

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)

Odată ce am găsit toate căile cele mai scurte de la vârful sursă, cele mai lungi căi vor fi doar negarea celor mai scurte căi.



Mai jos este implementarea abordării de mai sus:

C++
// A C++ program to find single source longest distances // in a DAG #include    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/dsa/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 adjStack 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 adjV 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/dsa/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. 
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 

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

Complexitatea timpului : Complexitatea temporală a sortării topologice este O(V + E). După ce a găsit ordinea topologică, algoritmul procesează toate nodurile și pentru fiecare vârf rulează o buclă pentru toate vârfurile adiacente. Întrucât totalul vârfurilor adiacente dintr-un grafic este O(E), bucla interioară rulează O(V + E) ori. Prin urmare, complexitatea de timp generală a acestui algoritm este O(V + E).

Complexitatea spațiului:
Complexitatea spațială a algoritmului de mai sus este O(V). Stocăm matricea de ieșire și o stivă pentru sortarea topologică.