Ruta de costo máximo en un gráfico no dirigido de modo que ningún borde se visite dos veces seguidas

Dado un gráfico no dirigido que tiene N vértices y M aristas y cada vértice está asociado con un costo y se da un vértice fuente S. La tarea es encontrar la ruta de costo máximo desde el vértice de origen S de modo que no se visite ningún borde consecutivamente 2 o más veces.

Ejemplos: 

Entrada: N = 5, M = 5, fuente = 1, costo [] = {2, 2, 8, 6, 9}, a continuación se muestra el gráfico dado: 
 

Salida: 21 
Explicación: 
La array de ruta de costo máximo se da como: 
1 -> 2 -> 0 -> 1 -> 4 
Costo = 2 + 8 + 2 + 2 + 9 = 21

Entrada: N = 8, M = 8, fuente = 3, costo[] = {10, 11, 4, 12, 3, 4, 7, 9} 
 

Salida: 46 

Explicación: 
La array de ruta de costo máximo se da como: 
3 -> 0 -> 2 -> 1 -> 7 
 

Enfoque: la idea es verificar si existe un bucle en el gráfico , luego todos los vértices del bucle deben atravesarse y luego atravesar el gráfico hacia los Nodes hoja con el costo máximo. Y si el bucle no existe, la declaración del problema se convierte para encontrar la ruta de costo máximo en cualquier gráfico dirigido.

 A continuación se muestra la declaración utilizada en el programa: 

  • dp[i]: almacena el costo total para atravesar el Node ‘i’ y todos sus Nodes secundarios.
  • vis[i]: marca los Nodes que han sido visitados.
  • canTake: almacena la suma resultante de todos los Nodes de ruta de costo máximo excluyendo el vértice hoja y su Node hijo, si existe.
  • mejor: almacena el costo de un Node hoja de costo máximo y su Node secundario (si existe).
  • check: variable booleana utilizada como bandera para encontrar un bucle en el gráfico, su valor cambia a 0 cuando se encuentra el bucle.

A continuación se muestran los pasos: 

  1. Realice el recorrido de DFS con la verificación de variable de indicador establecida en ‘1’, lo que inicialmente indica que no se encontró ningún bucle.
  2. Construya simultáneamente el dp[] para cada Node con el costo máximo actualizado hasta ese Node atravesado.
  3. Si se encuentra que el Node adyacente ya ha sido visitado y no es el Node principal, entonces se encuentra el bucle y se establece el valor de la verificación en 0 .
  4. Agregue el costo de todos los Nodes del ciclo a canTake .
  5. Después de atravesar los Nodes adyacentes del Node transversal, no se encuentra ningún bucle, entonces representa el costo de la ruta que conduce del bucle al vértice de la hoja y se actualiza mejor a dp[i] si dp[i] es mayor que mejor .
  6. Después de recorrer el gráfico, imprima la suma de canTake y best .

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

C++

// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// To store the resulting
// sum of the cost
int canTake;
 
// To store largest
// cost leaf vertex
int best;
 
vector<int> dp;
vector<bool> vis;
 
// DFS Traversal to find the update
// the maximum cost of from any
// node to leaf
int dfs(vector<vector<int> >& g,
        int* cost, int u, int pre)
{
 
    // Mark vertex as visited
    vis[u] = true;
 
    // Store vertex initial cost
    dp[u] = cost[u];
 
    // Initially assuming edge
    // not to be traversed
    bool check = 1;
 
    int cur = cost[u];
    for (auto& x : g[u]) {
 
        // Back edge found so,
        // edge can be part of
        // traversal
        if (vis[x] && x != pre) {
            check = 0;
        }
 
        // New vertex is found
        else if (!vis[x]) {
 
            // Bitwise AND the current
            // check with the returned
            // check by the previous
            // DFS Call
            check &= dfs(g, cost, x, u);
 
            // Adds parent and its
            // children cost
            cur = max(cur,
                      cost[u] + dp[x]);
        }
    }
 
    // Updates total cost of parent
    // including child nodes
    dp[u] = cur;
 
    // Edge is part of the cycle
    if (!check) {
 
        // Add cost of vertex
        // to the answer
        canTake += cost[u];
    }
    else {
 
        // Updates the largest
        // cost leaf vertex
        best = max(best, dp[u]);
    }
 
    return check;
}
 
// Function to find the maximum cost
// from source vertex such that no
// two edges is traversed twice
int FindMaxCost(vector<vector<int> >& g,
                int* cost, int source)
{
    // DFS Call
    dfs(g, cost, source, -1);
 
    // Print the maximum cost
    cout << canTake + best;
}
 
// Driver Code
int main()
{
    int n = 5, m = 5;
    dp.resize(n+1);
      vis.resize(n+1);
    // Cost Array
    int cost[] = { 2, 2, 8, 6, 9 };
 
    vector<vector<int> > g(n);
 
    // Given Graph
    g[0].push_back(1);
    g[1].push_back(0);
    g[0].push_back(2);
    g[2].push_back(0);
    g[0].push_back(3);
    g[3].push_back(0);
    g[1].push_back(2);
    g[2].push_back(1);
    g[1].push_back(4);
    g[4].push_back(1);
 
    // Given Source Node
    int source = 1;
 
    // Function Call
    FindMaxCost(g, cost, source);
    return 0;
}

Java

// Java program for the above approach
import java.util.*;
 
class GFG{
     
static int N = 100000;
 
// To store the resulting
// sum of the cost
static int canTake;
 
// To store largest
// cost leaf vertex
static int best;
 
static int []dp = new int[N];
static boolean []vis = new boolean[N];
 
// DFS Traversal to find the update
// the maximum cost of from any
// node to leaf
static boolean dfs(Vector<Integer> []g,
                   int []cost, int u, int pre)
{
     
    // Mark vertex as visited
    vis[u] = true;
 
    // Store vertex initial cost
    dp[u] = cost[u];
 
    // Initially assuming edge
    // not to be traversed
    boolean check = true;
 
    int cur = cost[u];
    for(int x : g[u])
    {
         
        // Back edge found so,
        // edge can be part of
        // traversal
        if (vis[x] && x != pre)
        {
            check = false;
        }
 
        // New vertex is found
        else if (!vis[x])
        {
 
            // Bitwise AND the current
            // check with the returned
            // check by the previous
            // DFS Call
            check = dfs(g, cost, x, u) ?
                    false : true;
 
            // Adds parent and its
            // children cost
            cur = Math.max(cur, cost[u] +
                                  dp[x]);
        }
    }
 
    // Updates total cost of parent
    // including child nodes
    dp[u] = cur;
 
    // Edge is part of the cycle
    if (!check)
    {
 
        // Add cost of vertex
        // to the answer
        canTake += cost[u];
    }
    else
    {
 
        // Updates the largest
        // cost leaf vertex
        best = Math.max(best, dp[u]);
    }
    return check;
}
 
// Function to find the maximum cost
// from source vertex such that no
// two edges is traversed twice
static void FindMaxCost(Vector<Integer> [] g,
                        int []cost, int source)
{
     
    // DFS call
    dfs(g, cost, source, -1);
 
    // Print the maximum cost
    System.out.print(canTake + best);
}
 
// Driver Code
public static void main(String[] args)
{
    int n = 5, m = 5;
 
    // Cost Array
    int cost[] = { 2, 2, 8, 6, 9 };
     
    @SuppressWarnings("unchecked")
    Vector<Integer> []g = new Vector[n];
    for(int i = 0; i < g.length; i++)
        g[i] = new Vector<Integer>();
         
    // Given Graph
    g[0].add(1);
    g[1].add(0);
    g[0].add(2);
    g[2].add(0);
    g[0].add(3);
    g[3].add(0);
    g[1].add(2);
    g[2].add(1);
    g[1].add(4);
    g[4].add(1);
 
    // Given Source Node
    int source = 1;
 
    // Function call
    FindMaxCost(g, cost, source);
}
}
 
// This code is contributed by Amit Katiyar

Python3

# Python3 program for the above approach
N = 100000
  
# To store the resulting
# sum of the cost
canTake = 0
  
# To store largest
# cost leaf vertex
best = 0
  
dp = [0 for i in range(N)]
vis = [0 for i in range(N)]
  
# DFS Traversal to find the update
# the maximum cost of from any
# node to leaf
def dfs(g, cost, u, pre):
     
    global canTake, best
     
    # Mark vertex as visited
    vis[u] = True
  
    # Store vertex initial cost
    dp[u] = cost[u]
  
    # Initially assuming edge
    # not to be traversed
    check = 1
  
    cur = cost[u]
     
    for x in g[u]:
  
        # Back edge found so,
        # edge can be part of
        # traversal
        if (vis[x] and x != pre):
            check = 0
             
        # New vertex is found
        elif (not vis[x]):
  
            # Bitwise AND the current
            # check with the returned
            # check by the previous
            # DFS Call
            check &= dfs(g, cost, x, u)
  
            # Adds parent and its
            # children cost
            cur = max(cur, cost[u] + dp[x])
  
    # Updates total cost of parent
    # including child nodes
    dp[u] = cur
  
    # Edge is part of the cycle
    if (not check):
  
        # Add cost of vertex
        # to the answer
        canTake += cost[u]
     
    else:
  
        # Updates the largest
        # cost leaf vertex
        best = max(best, dp[u])
     
    return check
  
# Function to find the maximum cost
# from source vertex such that no
# two edges is traversed twice
def FindMaxCost(g, cost, source):
   
    # DFS Call
    dfs(g, cost, source, -1)
  
    # Print the maximum cost
    print(canTake + best)
     
# Driver Code
if __name__=='__main__':
   
    n = 5
    m = 5
  
    # Cost Array
    cost = [ 2, 2, 8, 6, 9 ]
  
    g = [[] for i in range(n)]
  
    # Given Graph
    g[0].append(1)
    g[1].append(0)
    g[0].append(2)
    g[2].append(0)
    g[0].append(3)
    g[3].append(0)
    g[1].append(2)
    g[2].append(1)
    g[1].append(4)
    g[4].append(1)
  
    # Given Source Node
    source = 1
  
    # Function Call
    FindMaxCost(g, cost, source)
     
# This code is contributed by rutvik_56

C#

// C# program for
// the above approach
using System;
using System.Collections.Generic;
class GFG{
     
static int N = 100000;
 
// To store the resulting
// sum of the cost
static int canTake;
 
// To store largest
// cost leaf vertex
static int best;
 
static int []dp = new int[N];
static bool []vis = new bool[N];
 
// DFS Traversal to find the update
// the maximum cost of from any
// node to leaf
static bool dfs(List<int> []g,
                int []cost,
                int u, int pre)
{
  // Mark vertex as visited
  vis[u] = true;
 
  // Store vertex initial cost
  dp[u] = cost[u];
 
  // Initially assuming edge
  // not to be traversed
  bool check = true;
 
  int cur = cost[u];
  foreach(int x in g[u])
  {
    // Back edge found so,
    // edge can be part of
    // traversal
    if (vis[x] && x != pre)
    {
      check = false;
    }
 
    // New vertex is found
    else if (!vis[x])
    {
      // Bitwise AND the current
      // check with the returned
      // check by the previous
      // DFS Call
      check = dfs(g, cost, x, u) ?
              false : true;
 
      // Adds parent and its
      // children cost
      cur = Math.Max(cur, cost[u] + dp[x]);
    }
  }
 
  // Updates total cost of parent
  // including child nodes
  dp[u] = cur;
 
  // Edge is part of the cycle
  if (!check)
  {
    // Add cost of vertex
    // to the answer
    canTake += cost[u];
  }
  else
  {
    // Updates the largest
    // cost leaf vertex
    best = Math.Max(best, dp[u]);
  }
  return check;
}
 
// Function to find the maximum cost
// from source vertex such that no
// two edges is traversed twice
static void FindMaxCost(List<int> [] g,
                        int []cost, int source)
{
  // DFS call
  dfs(g, cost, source, -1);
 
  // Print the maximum cost
  Console.Write(canTake + best);
}
 
// Driver Code
public static void Main(String[] args)
{
  int n = 5, m = 5;
 
  // Cost Array
  int []cost = {2, 2, 8, 6, 9};
 
  List<int> []g = new List<int>[n];
   
  for(int i = 0; i < g.Length; i++)
    g[i] = new List<int>();
 
  // Given Graph
  g[0].Add(1);
  g[1].Add(0);
  g[0].Add(2);
  g[2].Add(0);
  g[0].Add(3);
  g[3].Add(0);
  g[1].Add(2);
  g[2].Add(1);
  g[1].Add(4);
  g[4].Add(1);
 
  // Given Source Node
  int source = 1;
 
  // Function call
  FindMaxCost(g, cost, source);
}
}
 
// This code is contributed by Princi Singh

Javascript

<script>
 
// Javascript program for
// the above approach
     
var N = 100000;
 
// To store the resulting
// sum of the cost
var canTake = 0;
 
// To store largest
// cost leaf vertex
var best = 0;
 
var dp = Array(N).fill(0);
var vis = Array(N).fill(false);
 
// DFS Traversal to find the update
// the maximum cost of from any
// node to leaf
function dfs(g, cost, u, pre)
{
  // Mark vertex as visited
  vis[u] = true;
 
  // Store vertex initial cost
  dp[u] = cost[u];
 
  // Initially assuming edge
  // not to be traversed
  var check = true;
 
  var cur = cost[u];
  for(var x of g[u])
  {
    // Back edge found so,
    // edge can be part of
    // traversal
    if (vis[x] && x != pre)
    {
      check = false;
    }
 
    // New vertex is found
    else if (!vis[x])
    {
      // Bitwise AND the current
      // check with the returned
      // check by the previous
      // DFS Call
      check = dfs(g, cost, x, u) ?
              false : true;
 
      // Adds parent and its
      // children cost
      cur = Math.max(cur, cost[u] + dp[x]);
    }
  }
 
  // Updates total cost of parent
  // including child nodes
  dp[u] = cur;
 
  // Edge is part of the cycle
  if (!check)
  {
    // push cost of vertex
    // to the answer
    canTake += cost[u];
  }
  else
  {
    // Updates the largest
    // cost leaf vertex
    best = Math.max(best, dp[u]);
  }
  return check;
}
 
// Function to find the maximum cost
// from source vertex such that no
// two edges is traversed twice
function FindMaxCost(g, cost, source)
{
  // DFS call
  dfs(g, cost, source, -1);
 
  // Print the maximum cost
  document.write(canTake + best);
}
 
// Driver Code
var n = 5, m = 5;
// Cost Array
var cost = [2, 2, 8, 6, 9];
var g = Array.from(Array(n), ()=>Array());
 
// Given Graph
g[0].push(1);
g[1].push(0);
g[0].push(2);
g[2].push(0);
g[0].push(3);
g[3].push(0);
g[1].push(2);
g[2].push(1);
g[1].push(4);
g[4].push(1);
// Given Source Node
var source = 1;
// Function call
FindMaxCost(g, cost, source);
 
</script>
Producción: 

21

 

Complejidad temporal: O(N + M) donde N es un número de vértices y M es el número de aristas.
Espacio Auxiliar: O(N + M) donde N es un número de vértices y M es un número de aristas. 

Publicación traducida automáticamente

Artículo escrito por sharadgoyal 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 *