Given a directed graph with N nodes and E edges where the weight of each edge is > 0, also given a source S and a destination D. The task is to find the path with the minimum product of edges from S to D. If there is no path from S to D, then print -1.
Examples:
Input: N = 3, E = 3, Edges = {{{1, 2}, 0.5}, {{1, 3}, 1.9}, {{2, 3}, 3}}, S = 1, and D = 3
Output: 1.5
Explanation:
The shortest path will be 1->2->3
with value 0.5*3 = 1.5Input: N = 3, E = 3, Edges = {{{1, 2}, 0.5}, {{2, 3}, 0.5}, {{3, 1}, 0.5}}, S = 1, and D = 3
Output: cycle detected
Approach: The idea is to use the bellman ford algorithm. It is because Dijkstra’s algorithm cannot be used here as it works only with non-negative edges. It is because while multiplying values between [0-1), the product keeps decreasing indefinitely and 0 is returned finally.
Moreover, cycles need to be detected because if a cycle exists, the product of this cycle will indefinitely decrease the product to 0 and the product will tend to 0. For, simplicity, we will report such cycles.
The following steps can be followed to compute the result:
- Initialize an array, dis[] with initial value as ‘inf’ except dis[S] as 1.
- Run a loop from 1 – N-1. For each edge in the graph:
- dis[edge.second] = min(dis[edge.second], dis[edge.first]*weight(edge))
- Run another loop for each edge in the graph, if any edge exits with (dis[edge.second] > dis[edge.first]*weight(edge)), then cycle is detected.
- If dist[d] in infinity, return -1, else return dist[d].
Below is the implementation of the above approach:
C++
// C++ implementation of the approach. #include <bits/stdc++.h> using namespace std; double inf = std:: numeric_limits< double >::infinity(); // Function to return the smallest // product of edges double bellman( int s, int d, vector<pair<pair< int , int >, double > > ed, int n) { // If the source is equal // to the destination if (s == d) return 0; // Array to store distances double dis[n + 1]; // Initialising the array for ( int i = 1; i <= n; i++) dis[i] = inf; dis[s] = 1; // Bellman ford algorithm for ( int i = 0; i < n - 1; i++) for ( auto it : ed) dis[it.first.second] = min(dis[it.first.second], dis[it.first.first] * it.second); // Loop to detect cycle for ( auto it : ed) { if (dis[it.first.second] > dis[it.first.first] * it.second) return -2; } // Returning final answer if (dis[d] == inf) return -1; else return dis[d]; } // Driver code int main() { int n = 3; vector<pair<pair< int , int >, double > > ed; // Input edges ed = { { { 1, 2 }, 0.5 }, { { 1, 3 }, 1.9 }, { { 2, 3 }, 3 } }; // Source and Destination int s = 1, d = 3; // Bellman ford double get = bellman(s, d, ed, n); if (get == -2) cout << "Cycle Detected" ; else cout << get; } |
Java
// Java implementation of the approach import java.util.ArrayList; import java.util.Arrays; import java.util.PriorityQueue; class Pair<K, V> { K first; V second; public Pair(K first, V second) { this .first = first; this .second = second; } } class GFG{ static final float inf = Float.POSITIVE_INFINITY; // Function to return the smallest // product of edges static float bellman( int s, int d, ArrayList<Pair<Pair<Integer, Integer>, Float>> ed, int n) { // If the source is equal // to the destination if (s == d) return 0 ; // Array to store distances float [] dis = new float [n + 1 ]; // Initialising the array Arrays.fill(dis, inf); dis[s] = 1 ; // Bellman ford algorithm for ( int i = 0 ; i < n - 1 ; i++) for (Pair<Pair<Integer, Integer>, Float> it : ed) dis[it.first.second] = Math.min(dis[it.first.second], dis[it.first.first] * it.second); // Loop to detect cycle for (Pair<Pair<Integer, Integer>, Float> it : ed) { if (dis[it.first.second] > dis[it.first.first] * it.second) return - 2 ; } // Returning final answer if (dis[d] == inf) return - 1 ; else return dis[d]; } // Driver code public static void main(String[] args) { int n = 3 ; // Input edges ArrayList<Pair<Pair<Integer, Integer>, Float>> ed = new ArrayList<>( Arrays.asList( new Pair<Pair<Integer, Integer>, Float>( new Pair<Integer, Integer>( 1 , 2 ), 0 .5f), new Pair<Pair<Integer, Integer>, Float>( new Pair<Integer, Integer>( 1 , 3 ), 1 .9f), new Pair<Pair<Integer, Integer>, Float>( new Pair<Integer, Integer>( 2 , 3 ), 3f))); // Source and Destination int s = 1 , d = 3 ; // Bellman ford float get = bellman(s, d, ed, n); if (get == - 2 ) System.out.println( "Cycle Detected" ); else System.out.println(get); } } // This code is contributed by sanjeev2552 |
Python3
# Python3 implementation of the approach. import sys inf = sys.maxsize; # Function to return the smallest # product of edges def bellman(s, d, ed, n) : # If the source is equal # to the destination if (s = = d) : return 0 ; # Array to store distances dis = [ 0 ] * (n + 1 ); # Initialising the array for i in range ( 1 , n + 1 ) : dis[i] = inf; dis[s] = 1 ; # Bellman ford algorithm for i in range (n - 1 ) : for it in ed : dis[it[ 1 ]] = min (dis[it[ 1 ]], dis[it[ 0 ]] * ed[it]); # Loop to detect cycle for it in ed : if (dis[it[ 1 ]] > dis[it[ 0 ]] * ed[it]) : return - 2 ; # Returning final answer if (dis[d] = = inf) : return - 1 ; else : return dis[d]; # Driver code if __name__ = = "__main__" : n = 3 ; # Input edges ed = { ( 1 , 2 ) : 0.5 , ( 1 , 3 ) : 1.9 , ( 2 , 3 ) : 3 }; # Source and Destination s = 1 ; d = 3 ; # Bellman ford get = bellman(s, d, ed, n); if (get = = - 2 ) : print ( "Cycle Detected" ); else : print (get); # This code is contributed by AnkitRai01 |
C#
// C# implementation of the approach using System; using System.Linq; using System.Collections.Generic; public class GFG{ public static float inf = 1000000000; // Function to return the smallest // product of edges public static float bellman( int s, int d, List<KeyValuePair<KeyValuePair< int , int >, float >> ed, int n) { // If the source is equal // to the destination if (s == d) return 0; // Array to store distances float [] dis = Enumerable.Repeat(inf, n+1).ToArray(); dis[s] = 1; // Bellman ford algorithm for ( int i = 0; i < n - 1; i++) foreach (KeyValuePair<KeyValuePair< int , int >, float > it in ed) dis[it.Key.Value] = Math.Min(dis[it.Key.Value], dis[it.Key.Key] * it.Value); // Loop to detect cycle foreach (KeyValuePair<KeyValuePair< int , int >, float > it in ed) { if (dis[it.Key.Value] > dis[it.Key.Key] * it.Value) return -2; } // Returning final answer if (dis[d] == inf) return -1; else return dis[d]; } // Driver code public static void Main( string [] args) { int n = 3; // Input edges List<KeyValuePair<KeyValuePair< int , int >, float >> ed = new List<KeyValuePair<KeyValuePair< int , int >, float >>(){ new KeyValuePair<KeyValuePair< int , int >, float >( new KeyValuePair< int , int >(1, 2), 0.5f), new KeyValuePair<KeyValuePair< int , int >, float >( new KeyValuePair< int , int >(1, 3), 1.9f), new KeyValuePair<KeyValuePair< int , int >, float >( new KeyValuePair< int , int >(2, 3), 3f)}; // Source and Destination int s = 1, d = 3; // Bellman ford float get = bellman(s, d, ed, n); if ( get == -2) Console.Write( "Cycle Detected" ); else Console.Write( get ); } } // This code is contributed by rrrtnx. |
Javascript
<script> // Javascript implementation of the approach. var inf = 1000000000; // Function to return the smallest // product of edges function bellman(s, d, ed, n) { // If the source is equal // to the destination if (s == d) return 0; // Array to store distances var dis = Array(n+1).fill(inf); dis[s] = 1; // Bellman ford algorithm for ( var i = 0; i < n - 1; i++) { for ( var j =0 ; j< ed.length; j++) { dis[ed[j][0][1]] = Math.min(dis[ed[j][0][1]], dis[ed[j][0][0]] * ed[j][1]); } } // Loop to detect cycle for ( var it in ed) { if (dis[it[0][1]] > dis[it[0][0]] * it[1]) return -2; } // Returning final answer if (dis[d] == inf) return -1; else return dis[d]; } // Driver code var n = 3; var ed; // Input edges ed = [ [ [ 1, 2 ], 0.5 ], [ [ 1, 3 ], 1.9 ], [ [ 2, 3 ], 3 ] ]; // Source and Destination var s = 1, d = 3; // Bellman ford var get = bellman(s, d, ed, n); if (get == -2) document.write( "Cycle Detected" ); else document.write( get); </script> |
1.5
Time complexity: O(E*V)
Auxiliary Space: O(V).
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!