Skip to content
Related Articles
Get the best out of our app
GFG App
Open App
geeksforgeeks
Browser
Continue

Related Articles

Shortest path with maximum score and fixed start/end node

Improve Article
Save Article
Like Article
Improve Article
Save Article
Like Article

Given a graph with N nodes and M edges with array A[] and integer C, the task is to find the maximum score. If visiting node i gives A[i] points for all i from 1 to N. It is necessary to start the traversal from node 1 and end the traversal on node 1. The cost of traversal is C * T2 where T is the distance traveled.

Examples:

Input: A[] = {0, 10, 20}, edges[][2] = { {1, 2}, {2, 3}, {3, 1} }, C = 1
Output: 24
Explanation:

  • The optimal traversal is 1 -> 2 -> 3 -> 1 -> 2 -> 3 -> 1
  • T = Total Distance travelled = 6 
  • The cost is 10 (1 -> 2) + 20 (2 -> 3) + 0 (3 -> 1) + 10 (1 -> 2)  + 20 (2 -> 3) + 0 (3 -> 1) – C * T2 = 60 – C * T2 = 60 – 1 * 62 = 24

     

example 1 :

Input: A[] = {0, 10, 20}, edges[][2] = { {1, 2}, {2, 3}, {3, 1} }, C= 100
Output: 0
Explanation: It’s optimal not to traverse at all.

Naive approach: The basic way to solve the problem is as follows:

The basic way to solve this problem is to generate all possible combinations by using a recursive approach.

Time Complexity: O(N!)
Auxiliary Space: O(1)

Efficient Approach:  The above approach can be optimized based on the following idea:

Dynamic programming can be used to solve this problem

  • dp[i][j] = the maximum score on traversing node i’th time ending on node j.
  • recurrence relation: dp[curTime][u] = max(dp[curTime][u], dp[curTime – 1][i] + A[u]);

Follow the steps below to solve the problem:

  • Declare a 2d array dp[maxTime][N] with all values initialized to -1 indicating no node is visited yet.
  • Base case dp[0][0] = 0, if we do not travel at all we get 0 coins.
  • Initialize the answer variable to keep track of the max score.
  • Iterate on all and for each day iterate on all nodes.
  • At the end of each day keep track of the maximum value possible.
  • Finally, return the answer.

Below is the implementation of the above approach:

C++




// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to calculate maximum coins
// during trips
void maximumCoins(int A[], int N, int edg[][2], int M,
                  int C)
{
 
    // Adjecency list
    vector<vector<int> > adj(N);
 
    for (int i = 0; i < M; i++) {
 
        // Travel from edg[i][0]
        // to edg[i][1]
        adj[--edg[i][0]].push_back(--edg[i][1]);
    }
 
    // dp table initialized with -1
    // indicating not visited
    vector<vector<int> > dp(1001, vector<int>(N, -1));
 
    // Base case
    dp[0][0] = 0;
 
    int ans = 0;
 
    // Simulating time from 0 to 1000
    for (int curTime = 0; curTime < 1000; curTime++) {
 
        // At each unit time iterate
        // on each node
        for (int i = 0; i < N; i++) {
 
            // If dp[d][i] == -1 then the
            // node can't be visited
            if (dp[curTime][i] != -1) {
                for (int u : adj[i]) {
 
                    // dp[curTime + 1][u]
                    // is max(current coins
                    // earned, previous
                    // node's earnings +
                    // current node's
                    // earnings)
                    dp[curTime + 1][u]
                        = max(dp[curTime + 1][u],
                              dp[curTime][i] + A[u]);
                }
            }
        }
        ans = max(ans, (dp[curTime][0]
                        - (C * curTime * curTime)));
    }
 
    cout << ans << "\n";
}
 
// Driver Code
int main()
{
 
    // Input 1
    int A[] = { 0, 10, 20 },
        edges[][2] = { { 1, 2 }, { 2, 3 }, { 3, 1 } },
        C = 1;
    int N = sizeof(A) / sizeof(A[0]);
    int M = 3;
 
    // Function Call
    maximumCoins(A, N, edges, M, C);
 
    // Input 2
    int A1[] = { 0, 10, 20 },
        edges1[][2] = { { 1, 2 }, { 2, 3 }, { 3, 1 } },
        C1 = 10;
    int N1 = sizeof(A1) / sizeof(A1[0]);
    int M1 = 3;
 
    // Function Call
    maximumCoins(A1, N1, edges1, M1, C1);
    return 0;
}


Java




import java.util.*;
 
public class Main {
 
    // Function to calculate maximum coins during trips
    public static void
    maximumCoins(int[] A, int N, int[][] edg, int M, int C)
    {
 
        // Adjacency list
        ArrayList<ArrayList<Integer> > adj
            = new ArrayList<ArrayList<Integer> >();
        for (int i = 0; i < N; i++) {
            adj.add(new ArrayList<Integer>());
        }
 
        for (int i = 0; i < M; i++) {
 
            // Travel from edg[i][0] to edg[i][1]
            adj.get(edg[i][0] - 1).add(edg[i][1] - 1);
        }
 
        // dp table initialized with -1 indicating not
        // visited
        int[][] dp = new int[1001][N];
        for (int i = 0; i < 1001; i++) {
            Arrays.fill(dp[i], -1);
        }
 
        // Base case
        dp[0][0] = 0;
 
        int ans = 0;
 
        // Simulating time from 0 to 1000
        for (int curTime = 0; curTime < 1000; curTime++) {
 
            // At each unit time iterate on each node
            for (int i = 0; i < N; i++) {
 
                // If dp[d][i] == -1 then the node can't be
                // visited
                if (dp[curTime][i] != -1) {
                    for (int u : adj.get(i)) {
 
                        // dp[curTime + 1][u] is max(current
                        // coins earned, previous node's
                        // earnings + current node's
                        // earnings)
                        dp[curTime + 1][u] = Math.max(
                            dp[curTime + 1][u],
                            dp[curTime][i] + A[u]);
                    }
                }
            }
            ans = Math.max(
                ans,
                (dp[curTime][0] - (C * curTime * curTime)));
        }
 
        System.out.println(ans);
    }
 
    // Driver Code
    public static void main(String[] args)
    {
 
        // Input 1
        int[] A = { 0, 10, 20 };
        int[][] edges = { { 1, 2 }, { 2, 3 }, { 3, 1 } };
        int C = 1;
        int N = A.length;
        int M = 3;
 
        // Function Call
        maximumCoins(A, N, edges, M, C);
 
        // Input 2
        int[] A1 = { 0, 10, 20 };
        int[][] edges1 = { { 1, 2 }, { 2, 3 }, { 3, 1 } };
        int C1 = 10;
        int N1 = A1.length;
        int M1 = 3;
 
        // Function Call
        maximumCoins(A1, N1, edges1, M1, C1);
    }
}
 
// This code is contributed by Prajwal Kandekar


Python3




# Python code to implement the approach
 
# Function to calculate maximum coins
# during trips
 
 
def maximumCoins(A, N, edg, M, C):
 
    # Adjacency list
    adj = [[] for i in range(N)]
 
    for i in range(M):
 
        # Travel from edg[i][0]
        # to edg[i][1]
        adj[edg[i][0]-1].append(edg[i][1]-1)
 
    # dp table initialized with -1
    # indicating not visited
    dp = [[-1 for i in range(N)] for j in range(1001)]
 
    # Base case
    dp[0][0] = 0
 
    ans = 0
 
    # Simulating time from 0 to 1000
    for curTime in range(1000):
 
        # At each unit time iterate
        # on each node
        for i in range(N):
 
            # If dp[d][i] == -1 then the
            # node can't be visited
            if dp[curTime][i] != -1:
                for u in adj[i]:
 
                    # dp[curTime + 1][u]
                    # is max(current coins
                    # earned, previous
                    # node's earnings +
                    # current node's
                    # earnings)
                    dp[curTime + 1][u] = max(dp[curTime + 1]
                                             [u], dp[curTime][i] + A[u])
 
        ans = max(ans, (dp[curTime][0] - (C * curTime * curTime)))
 
    print(ans)
 
 
# Driver Code
if __name__ == '__main__':
 
    # Input 1
    A = [0, 10, 20]
    edges = [[1, 2], [2, 3], [3, 1]]
    C = 1
    N = len(A)
    M = 3
 
    # Function Call
    maximumCoins(A, N, edges, M, C)
 
    # Input 2
    A1 = [0, 10, 20]
    edges1 = [[1, 2], [2, 3], [3, 1]]
    C1 = 10
    N1 = len(A1)
    M1 = 3
 
    # Function Call
    maximumCoins(A1, N1, edges1, M1, C1)


C#




using System;
using System.Collections.Generic;
 
class Program {
    // Function to calculate maximum coins during trips
    public static void
    maximumCoins(int[] A, int N, int[][] edg, int M, int C)
    {
 
        // Adjacency list
        List<List<int> > adj = new List<List<int> >();
        for (int i = 0; i < N; i++) {
            adj.Add(new List<int>());
        }
 
        for (int i = 0; i < M; i++) {
 
            // Travel from edg[i][0] to edg[i][1]
            adj[edg[i][0] - 1].Add(edg[i][1] - 1);
        }
 
        // dp table initialized with -1 indicating not
        // visited
        int[][] dp = new int[1001][];
        for (int i = 0; i < 1001; i++) {
            dp[i] = new int[N];
            for (int j = 0; j < N; j++) {
                dp[i][j] = -1;
            }
        }
 
        // Base case
        dp[0][0] = 0;
 
        int ans = 0;
 
        // Simulating time from 0 to 1000
        for (int curTime = 0; curTime < 1000; curTime++) {
 
            // At each unit time iterate on each node
            for (int i = 0; i < N; i++) {
 
                // If dp[d][i] == -1 then the node can't be
                // visited
                if (dp[curTime][i] != -1) {
                    foreach(int u in adj[i])
                    {
 
                        // dp[curTime + 1][u] is max(current
                        // coins earned, previous node's
                        // earnings + current node's
                        // earnings)
                        dp[curTime + 1][u] = Math.Max(
                            dp[curTime + 1][u],
                            dp[curTime][i] + A[u]);
                    }
                }
            }
            ans = Math.Max(
                ans,
                (dp[curTime][0] - (C * curTime * curTime)));
        }
 
        Console.WriteLine(ans);
    }
 
    // Driver Code
    public static void Main(string[] args)
    {
 
        // Input 1
        int[] A = { 0, 10, 20 };
        int[][] edges
            = { new int[] { 1, 2 }, new int[] { 2, 3 },
                new int[] { 3, 1 } };
        int C = 1;
        int N = A.Length;
        int M = 3;
 
        // Function Call
        maximumCoins(A, N, edges, M, C);
 
        // Input 2
        int[] A1 = { 0, 10, 20 };
        int[][] edges1
            = { new int[] { 1, 2 }, new int[] { 2, 3 },
                new int[] { 3, 1 } };
        int C1 = 10;
        int N1 = A1.Length;
        int M1 = 3;
 
        // Function Call
        maximumCoins(A1, N1, edges1, M1, C1);
    }
}
 
// This code is contributed by Tapesh(tapeshdua420)


Javascript




// Function to calculate maximum coins during trips
function maximumCoins(A, N, edg, M, C) {
    // Adjacency list
let adj = [];
for (let i = 0; i < N; i++) {
    adj.push([]);
}
 
for (let i = 0; i < M; i++) {
    // Travel from edg[i][0] to edg[i][1]
    adj[edg[i][0] - 1].push(edg[i][1] - 1);
}
 
// dp table initialized with -1 indicating not visited
let dp = [];
for (let i = 0; i < 1001; i++) {
    let temp = [];
    for (let j = 0; j < N; j++) {
        temp.push(-1);
    }
    dp.push(temp);
}
 
// Base case
dp[0][0] = 0;
 
let ans = 0;
 
// Simulating time from 0 to 1000
for (let curTime = 0; curTime < 1000; curTime++) {
 
    // At each unit time iterate on each node
    for (let i = 0; i < N; i++) {
 
        // If dp[d][i] == -1 then the node can't be visited
        if (dp[curTime][i] != -1) {
            for (let j = 0; j < adj[i].length; j++) {
 
                let u = adj[i][j];
 
                // dp[curTime + 1][u] is max(current coins earned, previous
                // node's earnings + current node's earnings)
                dp[curTime + 1][u] = Math.max(dp[curTime + 1][u], dp[curTime][i] + A[u]);
            }
        }
    }
 
    ans = Math.max(ans, (dp[curTime][0] - (C * curTime * curTime)));
}
 
console.log(ans);
}
 
// Driver Code
let A = [0, 10, 20];
let edges = [[1, 2], [2, 3], [3, 1]];
let C = 1;
let N = A.length;
let M = 3;
 
// Function Call
maximumCoins(A, N, edges, M, C);
 
let A1 = [0, 10, 20];
let edges1 = [[1, 2], [2, 3], [3, 1]];
let C1 = 10;
let N1 = A1.length;
let M1 = 3;
 
// Function Call
maximumCoins(A1, N1, edges1, M1, C1);


Output

24
0

Time Complexity: O((N + M) * D)
Auxiliary Space: O(N * D) where D is the maximum number of nodes visited.

Related Articles:


My Personal Notes arrow_drop_up
Last Updated : 19 Apr, 2023
Like Article
Save Article
Similar Reads
Related Tutorials