Minimum Cost using Dijkstra by Modifying Cost of an Edge


In this problem, we need to find the minimum path from 1 to N using Dijakstra’s algorithm, and we can update the cost of any single edge to cost/2.

Here, we will find each node's distance from the source node to the destination node. After that, we will take the shortest distance of node u from the source and node v from the destination and add them with the cost/2 of the u −> v edge. In this way, we will find the minimum cost of path 1 to N.

Problem statement − We have given an undirected graph in the form of a tuple. The tuple {p, q, r} represents the edge between p and q with cost r. We need to use Dijkstra’s algorithm to find the minimum cost for the path 1 to N. It is also given that we can perform only one operation so that we can update the cost of any edge to cost/2.

Sample examples

Input

[{1, {2, 7}}, {1, {3, 4}}, {1, {4, 8}}, {3, {4, 4}}, {4, {5, 3}}]

Output

7

Explanation − Here is the given graph.

                1
            /   |    \  
           2    3 - 4 - 5

Here, we need to reach from 1 to 5. So, two paths exist. One is 1 −> 3 −> 4 −> 5, and another is 1−> 4 −> 5. The cost of both paths is 11. If we take the second path and reduce the cost of 1−> 4 to 4 from 8, the cost of the path is 7.

Input

[{1, {2, 3}}, {2, {1, 6}}, {2, {3, 2}}]

Output

3

Explanation − We have given two edges between 1 to 2. So, we can consider the edge with cost 3 and update its value to 3/2 equal to 1. So, the cost of path 1 to 3 is only 3.

Approach

In this approach, we will use Dijkstra’s algorithm to find the distance of each node from the source and destination node. After that, for each edge connecting two vertices, we will take the distance of the start node from the source node and the end node from the destination node and add them with the cost/2. Also, we will track the minimum cost for paths 1 to N.

Algorithm

Step 1 − Define the list to store the graph.

Step 2 − Traverse through each given edge, and follow the below steps.

Step 2.1 − Take the source node, destination node, and cost from the current tuple.

Step 2.2 − Insert the {destination, cost} pair at the source index in the list, and inset the {source, cost} pair at the destination index in the list.

Step 3 − Furthermore, define the source_dist and dest_dist list to store the distance of each node from the source node and destination node, respectively.

Step 4 − Invoke the executeDijkstra() function two times to find the distance of each node from the start and end node, respectively.

Step 4.1 − In the executeDijkstra() function, resize the ‘dist’ list according to the total number of nodes and update the dist[source] with 0.

Step 4.2 − Define the priority queue and use the greater<pair<int, int>> comparator function to use the min heap with the priority queue. The priority queue will be used to store the distance of a current node from the source node and node value.

Step 4.3− Insert the source node into the queue.

Step 4.4 − Traverse the queue until it becomes empty. In the loop, get the first element from the queue and traverse its edges.

Step 4.5 − While traversing the edges, get the end node and the cost of the edge.

Step 4.6 − If the distance to the start node + cost of the edge is less than the distance to the end node, update the distance of the end node. Also, insert the updated pair into the queue.

Step 5− Define the ‘minCost’ variable and initialize it with the distance of 1 to N.

Step 6 − Start traversing all edges. Sum the distance of the start node from the source node, cost/2, and distance of the end node from the destination node. If the resultant value is greater than the minCost, update it.

Step 7 − Return the minCost value.

Example

#include <bits/stdc++.h>
using namespace std;
#define INF 1e9

void executeDijkstra(int source, int nodes, vector<pair<int, int>> list[], vector<int> &dist) {
    // Resizing
    dist.resize(nodes, INF);
    // Initialize source node with 0.
    dist[source] = 0;
    // To store edges cost
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> p_que;
    // Insert distance and source node
    p_que.push({dist[source], source});
    while (!p_que.empty()) {
        // Get the first node from the queue
        int start = p_que.top().second;
        // Pop the top node
        p_que.pop();
        // Traverse all connected nodes to the current node
        for (auto &ed : list[start]) {
            // Get the start and end node of the edge
            int end = ed.first;
            int cost = ed.second;
            // Updating the distance to minimum
            if (dist[start] + cost < dist[end]) {
                dist[end] = dist[start] + cost;
                p_que.push({dist[end], end});
            }
        }
    }
}
void getMinimumCost(vector<pair<int, pair<int, int>>> &edges, int nodes, int totalEdges) {
    vector<pair<int, int>> list[100005];
    // Traverse edges
    for (int p = 0; p < totalEdges; p++) {
        // Add graph parameters to list
        int source = edges[p].first;
        int destination = edges[p].second.first;
        int cost = edges[p].second.second;
        list[source].push_back({destination, cost});
        list[destination].push_back({source, cost});
    }
    // To store the distance of 1 to P and N to P
    vector<int> source_dist;
    vector<int> dest_dist;
    // For each vertex, find the path cost from the source node
    executeDijkstra(1, nodes + 1, list, source_dist);
    // For each vertex, find the path cost from the destination node
    executeDijkstra(nodes, nodes + 1, list, dest_dist);
    // To store minimum path cost
    int minCost = source_dist[nodes];
    for (auto &ed : edges) {
        // Get the edges
        int source = ed.first;
        int destination = ed.second.first;
        int cost = ed.second.second;
        // Cost for 1 to N = (1 to P) + (p to p + 1) + (P + 1 to N)
        int cur_cost = source_dist[source] + cost / 2 + dest_dist[destination];
        minCost = min(minCost, cur_cost);
    }
    cout << "The minimum cost for 1 to N after modifying any single edge is " << minCost << '\n';
}
int main() {
    int nodes = 5;
    int totalEdges = 5;
    vector<pair<int, pair<int, int>>> edges;
    edges.push_back({1, {2, 7}});
    edges.push_back({1, {3, 4}});
    edges.push_back({1, {4, 8}});
    edges.push_back({3, {4, 4}});
    edges.push_back({4, {5, 3}});
    getMinimumCost(edges, nodes, totalEdges);
    return 0;
}

Output

The minimum cost for 1 to N after modifying any single edge is 7

Time complexity − O(MlogN)

Space complexity − O(N)

Here, we have replaced only 1 edge cost with the cost/2. However, programmers can try to write code to replace the K edges’ cost for more practice.

Updated on: 02-Aug-2023

151 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements