Given a directed, weighted graph with n nodes and e edges, the task is to find the maximum product of edge weights in any path starting from node 1 and ending at node n.
Note: A path is a sequence of nodes starting and ending at particular nodes. The Graph does not contain loops and parallel edges.
Example:
Input:
Output: 224
Explanation: 7 * 4 * 8 = 224, as we have to travel from 1 to n i.e., 1 to 5 = > 1 – > 4 – > 2 – > 5
Approach: This can be solved with the following idea:
The idea is to apply the Dijkstra algorithm and change the meaning of the array which in the original algorithm used to store the value of the minimum sum of edge weights required to reach the current node to the maximum product of edge weights among all possible paths to reach the current node. We will update the update logic of Dijkstra to store the maximum product of edges in the array.
Steps involved in the implementation of code:
- Initialize a priority queue (pq) ( Max heap ) of pair ( Pair as it contains the first value of the maximum edge encountered and second current node).
- Insert into the priority queue a pair (1, 1) -> (1) denoting starting node 1 ( No edges encountered, and as we are going to do multiplication we need to initialize the first node with value 1)
- Initialize an array of size = no. of nodes, denoting the maximum edge weight encountered from node 1 to the current node.
-
Run a while loop while (pq.size() > 0):
- Pair p = pq.top() ;
- pq.pop() (removing top element from the priority queue)
-
for (nodes in adjacency list):
- update logic: update the array of the maximum product if the product of the current edge weight and previous node maximum product is greater than the current node maximum product value.
- Run a loop on the array to find the maximum answer.
Below is the implementation of the above approach:
// C++ Implementation of the above code #include <bits/stdc++.h> using namespace std;
// Function to find maximum weight // of graphfrom 1 to n int max_product_of_edges_in_path(
int n, vector<vector< int > >& roads)
{ // Declaring adjacency list
vector<vector<pair< int , int > > > adj(n + 1);
// Construction of adjacency list using
// the information of edges
for ( int i = 0; i < roads.size(); i++) {
adj[roads[i][0]].push_back(
{ roads[i][1], roads[i][2] });
// Directed graph : edge from
// roads[i][0] -> roads[i][1]
// of edge weight roads[i][2]
}
priority_queue<pair< int , int > > pq;
// Normal dijkstra
pq.push({ 1, 1 });
vector< int > max_product(n + 1, -1);
max_product[1] = 1;
while (!pq.empty()) {
pair< int , int > p = pq.top();
pq.pop();
if (max_product[p.second] > p.first)
continue ;
// Reduce extra iterations
// as in dijkstra
for ( auto it : adj[p.second]) {
// Update logic similar to
// dijkstra but with
// conditions changed
if (p.first * it.second
> max_product[it.first]) {
max_product[it.first] = p.first * it.second;
pq.push(
{ max_product[it.first], it.first });
}
}
}
return max_product[n];
} // Driver code int main()
{ int n = 5;
vector<vector< int > > edges;
edges.push_back({ 1, 2, 5 });
edges.push_back({ 1, 3, 6 });
edges.push_back({ 1, 4, 7 });
edges.push_back({ 4, 2, 4 });
edges.push_back({ 2, 5, 8 });
// Function call
cout << max_product_of_edges_in_path(n, edges) << "\n" ;
return 0;
} |
//Java Algorithm for the above approach import java.util.*;
public class GFG {
// Implementing Pair class
public static class Pair implements Comparable<Pair> {
int first;
int second;
Pair( int first, int second)
{
this .first = first;
this .second = second;
}
public int compareTo(Pair ob)
{
if ( this .first == ob.first) {
return this .second - ob.second;
}
return this .first - ob.first;
}
}
// Function to find maximum weight
// of graphfrom 1 to n
public static int max_product_of_edges_in_path(
int n, ArrayList<ArrayList<Integer> > roads)
{
// Declaring adjacency list
ArrayList<Pair>[] adj = new ArrayList[n + 1 ];
for ( int i = 0 ; i < n + 1 ; i++) {
adj[i] = new ArrayList<>();
}
// Construction of adjacency list using
// the information of edges
for ( int i = 0 ; i < roads.size(); i++) {
adj[roads.get(i).get( 0 )].add( new Pair(
roads.get(i).get( 1 ), roads.get(i).get( 2 )));
;
// Directed graph : edge from
// roads[i][0] -> roads[i][1]
// of edge weight roads[i][2]
}
PriorityQueue<Pair> pq = new PriorityQueue<>();
// Normal dijkstra
pq.add( new Pair( 1 , 1 ));
int [] max_product = new int [n + 1 ];
Arrays.fill(max_product, - 1 );
max_product[ 1 ] = 1 ;
while (!pq.isEmpty()) {
Pair p = pq.remove();
if (max_product[p.second] > p.first)
continue ;
// Reduce extra iterations
// as in dijkstra
for (Pair it : adj[p.second]) {
// Update logic similar to
// dijkstra but with
// conditions changed
if (p.first * it.second
> max_product[it.first]) {
max_product[it.first]
= p.first * it.second;
pq.add( new Pair(max_product[it.first],
it.first));
}
}
}
return max_product[n];
}
// Driver Code
public static void main(String[] args)
{
int n = 5 ;
ArrayList<ArrayList<Integer> > edges
= new ArrayList<ArrayList<Integer> >();
edges.add( new ArrayList<Integer>() {
{
add( 1 );
add( 2 );
add( 5 );
}
});
edges.add( new ArrayList<Integer>() {
{
add( 1 );
add( 3 );
add( 6 );
}
});
edges.add( new ArrayList<Integer>() {
{
add( 1 );
add( 4 );
add( 7 );
}
});
edges.add( new ArrayList<Integer>() {
{
add( 4 );
add( 2 );
add( 4 );
}
});
edges.add( new ArrayList<Integer>() {
{
add( 2 );
add( 5 );
add( 8 );
}
});
// Function Call
System.out.println(
max_product_of_edges_in_path(n, edges));
}
} |
# python Algorithm for the above approach import heapq
def max_product_of_edges_in_path(n, roads):
# Declaring adjacency list
adj = [[] for _ in range (n + 1 )]
# Construction of adjacency list using the information of edges
for road in roads:
adj[road[ 0 ]].append((road[ 1 ], road[ 2 ]))
# Directed graph: edge from road[0] -> road[1] of edge weight road[2]
pq = [] # priority queue using heapq module
# Normal Dijkstra's
heapq.heappush(pq, ( 1 , 1 ))
max_product = [ - 1 ] * (n + 1 )
max_product[ 1 ] = 1
while pq:
p = heapq.heappop(pq)
if max_product[p[ 1 ]] > p[ 0 ]:
continue
# Reduce extra iterations as in Dijkstra's
for it in adj[p[ 1 ]]:
# Update logic similar to Dijkstra's but with conditions changed
if p[ 0 ] * it[ 1 ] > max_product[it[ 0 ]]:
max_product[it[ 0 ]] = p[ 0 ] * it[ 1 ]
heapq.heappush(pq, (max_product[it[ 0 ]], it[ 0 ]))
return max_product[n]
# Driver code if __name__ = = '__main__' :
n = 5
edges = [
[ 1 , 2 , 5 ],
[ 1 , 3 , 6 ],
[ 1 , 4 , 7 ],
[ 4 , 2 , 4 ],
[ 2 , 5 , 8 ]
]
# Function call
print (max_product_of_edges_in_path(n, edges))
# This code is generated by Chetan Bargal
|
// C# code for the approach using System;
using System.Collections.Generic;
public class Solution {
// Function to find maximum weight
// of graphfrom 1 to n
public int MaxProductOfEdgesInPath( int n, int [][] roads) {
// Declaring adjacency list
List< int []>[] adj = new List< int []>[n+1];
for ( int i = 0; i <= n; i++) {
adj[i] = new List< int []>();
}
// Construction of adjacency list using the information of edges
foreach ( int [] road in roads) {
adj[road[0]].Add( new int [] { road[1], road[2] });
// Directed graph: edge from road[0] -> road[1] of edge weight road[2]
}
// Priority queue using SortedSet
SortedSet<Tuple< int , int >> pq = new SortedSet<Tuple< int , int >>();
// Normal Dijkstra's
pq.Add( new Tuple< int , int >(1, 1));
int [] maxProduct = new int [n+1];
for ( int i = 0; i <= n; i++) {
maxProduct[i] = -1;
}
maxProduct[1] = 1;
while (pq.Count > 0) {
Tuple< int , int > p = pq.Max;
pq.Remove(p);
if (maxProduct[p.Item2] > p.Item1) {
continue ;
}
// Reduce extra iterations as in Dijkstra's
foreach ( int [] it in adj[p.Item2]) {
// Update logic similar to Dijkstra's but with conditions changed
if (p.Item1 * it[1] > maxProduct[it[0]]) {
maxProduct[it[0]] = p.Item1 * it[1];
pq.Add( new Tuple< int , int >(maxProduct[it[0]], it[0]));
}
}
}
return maxProduct[n];
}
} // Driver code public class GFG {
static void Main( string [] args) {
int n = 5;
int [][] edges = {
new int [] {1, 2, 5},
new int [] {1, 3, 6},
new int [] {1, 4, 7},
new int [] {4, 2, 4},
new int [] {2, 5, 8}
};
// Function call
Solution solution = new Solution();
Console.WriteLine(solution.MaxProductOfEdgesInPath(n, edges));
}
} |
// Javascript implementation of the above code // Function to find maximum weight // of graph from 1 to n function maxProductOfEdgesInPath(n, roads) {
// Declaring adjacency list
const adj = Array(n + 1)
.fill()
.map(() => []);
// Construction of adjacency list using
// the information of edges
for (let i = 0; i < roads.length; i++) {
adj[roads[i][0]].push([roads[i][1], roads[i][2]]);
// Directed graph: edge from
// roads[i][0] -> roads[i][1]
// of edge weight roads[i][2]
}
const pq = [];
// Normal dijkstra
pq.push([1, 1]);
const maxProduct = Array(n + 1).fill(-1);
maxProduct[1] = 1;
while (pq.length > 0) {
const [pFirst, pSecond] = pq.shift();
if (maxProduct[pSecond] > pFirst) continue ;
// Reduce extra iterations
// as in dijkstra
for (const [itFirst, itSecond] of adj[pSecond]) {
// Update logic similar to
// dijkstra but with
// conditions changed
if (pFirst * itSecond > maxProduct[itFirst]) {
maxProduct[itFirst] = pFirst * itSecond;
pq.push([maxProduct[itFirst], itFirst]);
}
}
}
return maxProduct[n];
} // Driver code const n = 5; const edges = [ [1, 2, 5],
[1, 3, 6],
[1, 4, 7],
[4, 2, 4],
[2, 5, 8],
]; // Function call console.log(maxProductOfEdgesInPath(n, edges)); |
224
Time complexity: O(NLogN)
Auxiliary Space: O(N)