Skip to content
Related Articles

Related Articles

Improve Article

Maximum cost path in an Undirected Graph such that no edge is visited twice in a row

  • Difficulty Level : Hard
  • Last Updated : 30 Jun, 2021

Given an undirected graph having N vertices and M edges and each vertex is associated with a cost and a source vertex S is given. The task is to find the maximum cost path from source vertex S such that no edge is visited consecutively 2 or more times.

Examples: 

Input: N = 5, M = 5, source = 1, cost[] = {2, 2, 8, 6, 9}, Below is the given graph: 
 

Output: 21 
Explanation: 
The maximum cost path matrix is given as: 
1 -> 2 -> 0 -> 1 -> 4 
Cost = 2 + 8 + 2 + 2 + 9 = 21



Input: N = 8, M = 8, source = 3, cost[] = {10, 11, 4, 12, 3, 4, 7, 9} 
 

Output: 46 
Explanation: 
The maximum cost path matrix is given as: 
3 -> 0 -> 2 -> 1 -> 7 
 

Approach: The idea is to check if there exists a loop exists in the graph, then all vertices of the loop need to be traversed and then traverse graph towards the leaf nodes with the maximum cost. And if the loop does not exist then the problem statement converts to find maximum cost path in any directed graph.

 Below are the declaration used in the program: 

  • dp[i]: stores the total cost to traverse the node ‘i’ and all it’s children node.
  • vis[i]: marks the nodes which have been visited.
  • canTake: stores the resultant sum of all node of maximum cost path excluding the leaf vertex and its children node, if it exists.
  • best: stores the cost of a maximum cost leaf node and its children node(if it exists).
  • check: boolean variable used as a flag to find a loop in the graph, its value changes to 0 when the loop is found.

Below are the steps: 

  1. Perform DFS traversal with flag variable check set to ‘1’ initially denoting no loop found.
  2. Simultaneously build the dp[] for each node with the maximum cost updated till that traversed node.
  3. If the adjacent node is found to be already visited and it is not the parent node then the loop is found and set the value of the check to 0.
  4. Add the cost of all nodes of the loop to canTake.
  5. After traversing adjacent nodes of the traversing node, no loop is found, then it represents the cost of the path leading from loop to leaf vertex and updates best to dp[i] if dp[i] is greater than best.
  6. After traversal of the graph, print the sum of canTake and best.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
const int N = 100000;
 
// To store the resulting
// sum of the cost
int canTake;
 
// To store largest
// cost leaf vertex
int best;
 
int dp[N];
bool vis[N];
 
// 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;
 
    // 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>
Output: 
21

 

Time Complexity: O(N + M) where N is a number of vertices and M is the number of edges.
Auxiliary Space: O(N + M) where N is a number of vertices and M is a number of edges. 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :