Open In App

Minimum Cost using Dijkstra by Modifying Cost of an Edge

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

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:
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:
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
 

  1. 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[].
  2. 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[].
  3. Declare a variable minCost and assign it to a very large number initially.
  4. 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 
 

  1. Repeat this process for all the edges and correspondingly update the minCost variable.
     
  2. 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.


Output

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.
 



Last Updated : 27 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads