Minimum Cost using Dijkstra by Modifying Cost of an Edge
Given an undirected weighted graph of N nodes and M edges in the form of a tuple lets say {X, Y, Z} such that there is an edge with cost Z between X and Y. We are supposed to compute the minimum cost of traversal from node 1 to N. However, we can perform one operation before the traversal such that we can reduce the cost of any edge lets say, C to C / 2 (integer division).
Examples:
Input: N = 3, M = 4, Edges = {{1, 2, 3}, {2, 3, 1}, {1, 3, 7}, {2, 1, 5}}
Output: 2
Explanation:
Minimum Cost from source node 1 to destination node N is = 3/2 + 1 = 1 + 1 = 2.
Input: N = 3, M = 3, Edges = {{2, 3, 1}, {1, 3, 7}, {2, 1, 5}}
Output: 2
Explanation:
Minimum Cost from source node 1 to destination node N is = 7/2 = 3.
Approach: The idea is to consider every edge to be modified and try to minimize the overall cost by reducing its cost. The main idea is to break the path between node 1 to N into the path from 1 to any vertex u i.e., path(1 to u) and from node N to any vertex v i.e., path(n to v) for all u and v such that u to v forms an edge. We can easily compute the distance from any node lets say, source to all other nodes in the graph by applying single source shortest path algorithm, Dijkstra Algorithm. In this problem we would be applying the Dijkstra Algorithm twice by choosing sources as 1 and N separately and storing the cost to reach each node in the array dist_from_source[] and dist_from_dest[] respectively.
After we have computed these two arrays we can easily compute the cost associated after modifying each edge. Lets consider an edge u to v and let the cost associated with it be c. If we try to modify this edge we can compute the minimum cost from 1 to N as dist_from_source[u] + dist_from_dest[v] + c / 2. Doing this for all the edges and minimizing it we can get the minimum cost to travel from source 1 to destination N.
- Perform a Dijkstra Algorithm to find the single source shortest path for all the vertex from node 1 and store it in an array as dist_from_source[].
- Perform a Dijkstra Algorithm to find the single source shortest path for all the vertex from node N and store it in an array as dist_from_dest[].
- Declare a variable minCost and assign it to a very large number initially.
- Traverse all the given edges [u, v, c] and reduce it like formula discussed above and update the minCost variable as:
minCost = min(minCost, dist_from_source[u] + c/2 + dist_from_dest[v])
where,
c is the cost of current edge,
dist_from_source[u] is cost of path from node 1 to u
dist_from_source[v] is cost of path from node N to v
- Repeat this process for all the edges and correspondingly update the minCost variable.
- Print the value of minCost after the above step.
Below is the implementation of the above approach:
C++14
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; #define INF 1e9 // Function for Dijkstra Algorithm to // find single source shortest path void dijkstra( int source, int n, vector<pair< int , int > > adj[], vector< int >& dist) { // Resize dist[] to N and assign // any large value to it dist.resize(n, INF); // Initialise distance of source // node as 0 dist = 0; // Using min-heap priority_queue // for sorting wrt edges_cost priority_queue<pair< int , int >, vector<pair< int , int > >, greater<pair< int , int > > > pq; // Push the current dist // and source to pq pq.push({ dist, source }); // Until priority queue is empty while (!pq.empty()) { // Store the cost of linked // node to edges int u = pq.top().second; // int d = pq.top().first; // Pop the top node pq.pop(); // Iterate over edges for ( auto & edge : adj[u]) { // Find the starting and // ending vertex of edge int v = edge.first; int w = edge.second; // Update the distance of // node v to minimum of // dist[u] + w if it is // minimum if (dist[u] + w < dist[v]) { dist[v] = dist[u] + w; pq.push({ dist[v], v }); } } } } // Function to find the minimum cost // between node 1 to node n void minCostPath( vector<pair< int , pair< int , int > > >& edges, int n, int M) { // To create Adjacency List vector<pair< int , int > > adj[100005]; // Iterate over edges for ( int i = 0; i < M; i++) { // Get source, destination and // edges of edges[i] int x = edges[i].first; int y = edges[i].second.first; int z = edges[i].second.second; // Create Adjacency List adj[x].push_back({ y, z }); adj[y].push_back({ x, z }); } // To store the cost from node 1 // and node N vector< int > dist_from_source; vector< int > dist_from_dest; // Find the cost of travel between // source(1) to any vertex dijkstra(1, n + 1, adj, dist_from_source); // Find the cost of travel between // destination(n) to any vertex dijkstra(n, n + 1, adj, dist_from_dest); // Initialise the minimum cost int min_cost = dist_from_source[n]; // Traverse the edges for ( auto & it : edges) { // Get the edges int u = it.first; int v = it.second.first; int c = it.second.second; // Find the current cost from // node 1 to u and node u to v // and node v to N with only // current edge cost reduced // to half int cur_cost = dist_from_source[u] + c / 2 + dist_from_dest[v]; // Update the min_cost min_cost = min(min_cost, cur_cost); } // Print the minimum cost cout << min_cost << '\n' ; } // Driver Code int main() { // Give Nodes and Edges int N = 3; int M = 4; // Given Edges with cost vector<pair< int , pair< int , int > > > edges; edges.push_back({ 1, { 2, 3 } }); edges.push_back({ 2, { 3, 1 } }); edges.push_back({ 1, { 3, 7 } }); edges.push_back({ 1, { 3, 7 } }); // Function Call minCostPath(edges, N, M); return 0; } |
Javascript
<script> // Javascript program for the above approach // Function for Dijkstra Algorithm to // find single source shortest path function dijkstra(source, n, adj, dist) { // Resize dist[] to N and assign // any large value to it dist = Array(n).fill(1000000000); // Initialise distance of source // node as 0 dist = 0; // Using min-heap priority_queue // for sorting wrt edges_cost var pq = []; // Push the current dist // and source to pq pq.push([dist, source]); // Until priority queue is empty while (pq.length!=0) { // Store the cost of linked // node to edges var u = pq[pq.length-1][1]; // int d = pq.top()[0]; // Pop the top node pq.pop(); // Iterate over edges for ( var edge of adj[u]) { // Find the starting and // ending vertex of edge var v = edge[0]; var w = edge[1]; // Update the distance of // node v to minimum of // dist[u] + w if it is // minimum if (dist[u] + w < dist[v]) { dist[v] = dist[u] + w; pq.push([dist[v], v ]); } } pq.sort(); } return dist; } // Function to find the minimum cost // between node 1 to node n function minCostPath(edges, n, M) { // To create Adjacency List var adj = Array.from(Array(100005), ()=> new Array()); // Iterate over edges for ( var i = 0; i < M; i++) { // Get source, destination and // edges of edges[i] var x = edges[i][0]; var y = edges[i][1][0]; var z = edges[i][1][1]; // Create Adjacency List adj[x].push([y, z ]); adj[y].push([x, z ]); } // To store the cost from node 1 // and node N var dist_from_source = []; var dist_from_dest = []; // Find the cost of travel between // source(1) to any vertex dist_from_source = dijkstra(1, n + 1, adj, dist_from_source); // Find the cost of travel between // destination(n) to any vertex dist_from_dest = dijkstra(n, n + 1, adj, dist_from_dest); // Initialise the minimum cost var min_cost = dist_from_source[n]; // Traverse the edges for ( var it of edges) { // Get the edges var u = it[0]; var v = it[1][0]; var c = it[1][1]; // Find the current cost from // node 1 to u and node u to v // and node v to N with only // current edge cost reduced // to half var cur_cost = dist_from_source[u] + parseInt(c / 2) + dist_from_dest[v]; // Update the min_cost min_cost = Math.min(min_cost, cur_cost); } // Print the minimum cost document.write( min_cost + "<br>" ); } // Driver Code // Give Nodes and Edges var N = 3; var M = 3; // Given Edges with cost var edges = []; edges.push([2, [3, 1]]); edges.push([1, [3, 7 ]]); edges.push([2, [1, 5 ]]); // Function Call minCostPath(edges, N, M); // This code is contributed by noob2000. </script> |
Python3
# Python3 program for the above approach import heapq as hq INF = 1e9 # Function for Dijkstra Algorithm to # find single source shortest path def dijkstra(source, n, adj, dist): # Initialise distance of source # node as 0 dist = 0 # Using min-heap priority_queue # for sorting wrt edges_cost pq = [] # Push the current dist # and source to pq hq.heappush(pq, (dist, source)) # Until priority queue is empty while pq: # Store the cost of linked # node to edges d, u = hq.heappop(pq) # Iterate over edges for v,w in adj[u]: # Update the distance of # node v to minimum of # dist[u] + w if it is # minimum if dist[u] + w < dist[v]: dist[v] = dist[u] + w hq.heappush(pq, (dist[v], v)) # Function to find the minimum cost # between node 1 to node n def minCostPath(edges, n, M): # To create Adjacency List adj = [[] for _ in range ( 100005 )] # Iterate over edges for i in range (M): # Get source, destination and # edges of edges[i] x = edges[i][ 0 ] y = edges[i][ 1 ][ 0 ] z = edges[i][ 1 ][ 1 ] # Create Adjacency List adj[x].append((y, z)) adj[y].append((x, z)) # To store the cost from node 1 # and node N dist_from_source = [INF] * (n + 1 ) dist_from_dest = [INF] * (n + 1 ) # Find the cost of travel between # source(1) to any vertex dijkstra( 1 , n + 1 , adj, dist_from_source) # Find the cost of travel between # destination(n) to any vertex dijkstra(n, n + 1 , adj, dist_from_dest) # Initialise the minimum cost min_cost = dist_from_source[n] # Traverse the edges for it in edges: # Get the edges u = it[ 0 ] v = it[ 1 ][ 0 ] c = it[ 1 ][ 1 ] # Find the current cost from # node 1 to u and node u to v # and node v to N with only # current edge cost reduced # to half cur_cost = dist_from_source[u] + c / / 2 + dist_from_dest[v] # Update the min_cost min_cost = min (min_cost, cur_cost) # Print minimum cost print (min_cost) # Driver Code if __name__ = = "__main__" : # Give Nodes and Edges N = 3 M = 3 # Given Edges with cost edges = [] edges.append(( 2 , ( 3 , 1 ))) edges.append(( 1 , ( 3 , 7 ))) edges.append(( 2 , ( 1 , 5 ))) # Function Call minCostPath(edges, N, M) |
C#
// C# program for the above approach using System; using System.Collections.Generic; class Program { const int INF = 1000000000; // Function for Dijkstra Algorithm to // find single source shortest path static void Dijkstra( int source, int n, List<( int , int )>[] adj, int [] dist) { // Resize dist[] to N and assign // any large value to it Array.Fill(dist, INF); // Initialise distance of source // node as 0 dist = 0; // Using min-heap priority_queue // for sorting wrt edges_cost var pq = new SortedSet<( int , int )>(Comparer<( int , int )>.Create((a, b) => a.Item1.CompareTo(b.Item1))); // Push the current dist // and source to pq pq.Add((dist, source)); // Until priority queue is empty while (pq.Count > 0) { // Store the cost of linked // node to edges var u = pq.Min; // int d = pq.top().first; // Pop the top node pq.Remove(u); // Iterate over edges foreach ( var edge in adj[u.Item2]) { // Find the starting and // ending vertex of edge int v = edge.Item1, w = edge.Item2; // Update the distance of // node v to minimum of // dist[u] + w if it is // minimum if (dist[u.Item2] + w < dist[v]) { pq.Remove((dist[v], v)); dist[v] = dist[u.Item2] + w; pq.Add((dist[v], v)); } } } } // Function to find the minimum cost // between node 1 to node n static void MinCostPath(List<( int , ( int , int ))> edges, int n, int M) { // To create Adjacency List var adj = new List<( int , int )>[100005]; for ( int i = 0; i < adj.Length; i++) adj[i] = new List<( int , int )>(); // Iterate over edges foreach ( var edge in edges) { // Get source, destination and // edges of edges[i] int x = edge.Item1, y = edge.Item2.Item1, z = edge.Item2.Item2; // Create Adjacency List adj[x].Add((y, z)); adj[y].Add((x, z)); } // To store the cost from node 1 // and node N var distFromSource = new int [n + 1]; var distFromDest = new int [n + 1]; // Find the cost of travel between // source(1) to any vertex Dijkstra(1, n + 1, adj, distFromSource); // Find the cost of travel between // destination(n) to any vertex Dijkstra(n, n + 1, adj, distFromDest); // Initialise the minimum cost int minCost = distFromSource[n]; // Traverse the edges foreach ( var it in edges) { // Get the edges int u = it.Item1, v = it.Item2.Item1, c = it.Item2.Item2; // Find the current cost from // node 1 to u and node u to v // and node v to N with only // current edge cost reduced // to half int curCost = distFromSource[u] + c / 2 + distFromDest[v]; // Update the min_cost minCost = Math.Min(minCost, curCost); } // Print the minimum cost Console.WriteLine(minCost); } // Driver Code static void Main() { // Give Nodes and Edges int N = 3; int M = 3; // Given Edges with cost var edges = new List<( int , ( int , int ))> { (2, (3, 1)), (1, (3, 7)), (2, (1, 5)) }; MinCostPath(edges, N, M); } } |
Java
// java code addition import java.util.regex.Matcher; import java.util.regex.Pattern; import java.io.*; import java.util.*; // Java code additin public class Main { static final int INF = 1000000000 ; // Function for Dijkstra Algorithm to // find single source shortest path static void dijkstra( int source, int n, ArrayList<ArrayList<ArrayList<Integer>>> adj, ArrayList<Integer> dist) { // Resize dist[] to N and assign // any large value to it Collections.fill(dist, INF); // Initialise distance of source // node as 0 dist.set(source, 0 ); // Using min-heap priority_queue // for sorting wrt edges_cost PriorityQueue<ArrayList<Integer>> pq = new PriorityQueue<>(Comparator.comparing(o -> o.get( 0 ))); // Push the current dist // and source to pq pq.add( new ArrayList<>(Arrays.asList(dist.get(source), source))); // Until priority queue is empty while (!pq.isEmpty()) { // Store the cost of linked // node to edges int u = pq.peek().get( 1 ); // Pop the top node pq.poll(); // Iterate over edges for (ArrayList<Integer> edge : adj.get(u)) { // Find the starting and // ending vertex of edge int v = edge.get( 0 ); int w = edge.get( 1 ); // Update the distance of // node v to minimum of // dist[u] + w if it is // minimum if (dist.get(u) + w < dist.get(v)) { dist.set(v, dist.get(u) + w); pq.add( new ArrayList<>(Arrays.asList(dist.get(v), v))); } } } } // Function to find the minimum cost // between node 1 to node n static void minCostPath( ArrayList<ArrayList<Integer>> edges, int n, int M) { // To create Adjacency List ArrayList<ArrayList<ArrayList<Integer>>> adj = new ArrayList<>(n + 1 ); for ( int i = 0 ; i <= n; i++) { adj.add( new ArrayList<>()); } // Iterate over edges for ( int i = 0 ; i < M; i++) { // Get source, destination and // edges of edges[i] int x = edges.get(i).get( 0 ); int y = edges.get(i).get( 1 ); int z = edges.get(i).get( 2 ); // Create Adjacency List adj.get(x).add( new ArrayList<>(Arrays.asList(y, z))); adj.get(y).add( new ArrayList<>(Arrays.asList(x, z))); } // To store the cost from node 1 // and node N ArrayList<Integer> dist_from_source = new ArrayList<>(Collections.nCopies(n + 1 , 0 )); ArrayList<Integer> dist_from_dest = new ArrayList<>(Collections.nCopies(n + 1 , 0 )); // Find the cost of travel between // source(1) to any vertex dijkstra( 1 , n + 1 , adj, dist_from_source); // Find the cost of travel between // destination(n) to any vertex dijkstra(n, n + 1 , adj, dist_from_dest); // Initialise the minimum cost int min_cost = dist_from_source.get(n); // Traverse the edges for (ArrayList<Integer> it : edges) { // Get the edges int u = it.get( 0 ); int v = it.get( 1 ); int c = it.get( 2 ); // Find the current cost from // node 1 to u and node u to v // and node v to N with only // current edge cost reduced // to half int cur_cost = dist_from_source.get(u) + c / 2 + dist_from_dest.get(v); // Update the min_cost min_cost = Math.min(min_cost, cur_cost); } System.out.println(min_cost); } public static void main(String[] args) { int N = 3 ; int M = 4 ; // Given Edges with cost ArrayList<ArrayList<Integer>> edges = new ArrayList<>(); ArrayList<Integer> edge1 = new ArrayList<>(); edge1.add( 1 ); edge1.add( 2 ); edge1.add( 3 ); edges.add(edge1); ArrayList<Integer> edge2 = new ArrayList<>(); edge2.add( 2 ); edge2.add( 3 ); edge2.add( 1 ); edges.add(edge2); ArrayList<Integer> edge3 = new ArrayList<>(); edge3.add( 1 ); edge3.add( 3 ); edge3.add( 7 ); edges.add(edge3); ArrayList<Integer> edge4 = new ArrayList<>(); edge4.add( 1 ); edge4.add( 3 ); edge4.add( 7 ); edges.add(edge4); // Function Call minCostPath(edges, N, M); } } // The code is contributed by Nidhi goel. |
2
Time Complexity: O(M log N), where N is the number of nodes and M is the number of edges.
Auxiliary Space: O(N), where N is the number of nodes.
Please Login to comment...