Open In App

Minimum cost path from source node to destination node via an intermediate node

Improve
Improve
Like Article
Like
Save
Share
Report

Given an undirected weighted graph. The task is to find the minimum cost of the path from source node to the destination node via an intermediate node. 

Note: If an edge is traveled twice, only once weight is calculated as cost. 

Examples: 

Input: source = 0, destination = 2, intermediate = 3; 
Output:
The minimum cost path 0->1->3->1->2 .
The edge (1-3) occurs twice in the path, but its weight is added only once to the answer.

Input: source = 0, destination = 2, intermediate = 1; 
Output:
The minimum cost path is 0->1>2 

Approach: 

Let suppose take a path P1 from Source to intermediate, and a path P2 from intermediate to destination. There can be some common edges among these 2 paths. Hence, the optimal path will always have the following form: for any node U, the walk consists of edges on the shortest path from Source to U, from intermediate to U, and from destination to U. Hence, if dist(a, b) is the cost of shortest path between node a and b, the required minimum cost path will be min{ dist(Source, U) + dist(intermediate, U) + dist(destination, U) } for all U. The Minimum distance of all nodes from Source, intermediate, and destination can be found by doing Dijkstra’s Shortest Path algorithm from these 3 nodes. 

Below is the implementation of the above approach. 

C++




// CPP program to find minimum distance between
// source and destination node and visiting
// of intermediate node is compulsory
#include <bits/stdc++.h>
using namespace std;
#define MAXN 100005
 
// to store mapped values of graph
vector<pair<int, int> > v[MAXN];
 
// to store distance of
// all nodes from the source node
int dist[MAXN];
 
// Dijkstra's algorithm to find
// shortest path from source to node
void dijkstra(int source, int n)
{
    // set all the vertices
    // distances as infinity
    for (int i = 0; i < n; i++)
        dist[i] = INT_MAX;
 
    // set all vertex as unvisited
    bool vis[n];
    memset(vis, false, sizeof vis);
 
    // make distance from source
    // vertex to source vertex is zero
    dist = 0;
 
    // // multiset do the job
    // as a min-priority queue
    multiset<pair<int, int> > s;
 
    // insert the source node with distance = 0
    s.insert({ 0, source });
 
    while (!s.empty()) {
        pair<int, int> p = *s.begin();
        // pop the vertex with the minimum distance
        s.erase(s.begin());
 
        int x = p.second;
        int wei = p.first;
 
        // check if the popped vertex
        // is visited before
        if (vis[x])
            continue;
 
        vis[x] = true;
 
        for (int i = 0; i < v[x].size(); i++) {
            int e = v[x][i].first;
            int w = v[x][i].second;
 
            // check if the next vertex
            // distance could be minimized
            if (dist[x] + w < dist[e]) {
 
                dist[e] = dist[x] + w;
 
                // insert the next vertex
                // with the updated distance
                s.insert({ dist[e], e });
            }
        }
    }
}
 
// function to add edges in graph
void add_edge(int s, int t, int weight)
{
    v[s].push_back({ t, weight });
    v[t].push_back({ s, weight });
}
 
// function to find the minimum shortest path
int solve(int source, int destination,
               int intermediate, int n)
{
    int ans = INT_MAX;
 
    dijkstra(source, n);
 
    // store distance from source to
    // all other vertices
    int dsource[n];
    for (int i = 0; i < n; i++)
        dsource[i] = dist[i];
 
    dijkstra(destination, n);
    // store distance from destination
    // to all other vertices
    int ddestination[n];
    for (int i = 0; i < n; i++)
        ddestination[i] = dist[i];
 
    dijkstra(intermediate, n);
    // store distance from intermediate
    // to all other vertices
    int dintermediate[n];
    for (int i = 0; i < n; i++)
        dintermediate[i] = dist[i];
 
    // find required answer
    for (int i = 0; i < n; i++)
        ans = min(ans, dsource[i] + ddestination[i]
                                  + dintermediate[i]);
 
    return ans;
}
 
// Driver code
int main()
{
 
    int n = 4;
    int source = 0, destination = 2, intermediate = 3;
 
    // add edges in graph
    add_edge(0, 1, 1);
    add_edge(1, 2, 2);
    add_edge(1, 3, 3);
 
    // function call for minimum shortest path
    cout << solve(source, destination, intermediate, n);
 
    return 0;
}


Java




import java.util.*;
// Java program to find minimum distance between
// source and destination node and visiting
// of intermediate node is compulsory
public class Main {
 
    static int MAXN = 100005;
  // to store mapped values of graph
    static List<Pair<Integer, Integer>>[] v = new ArrayList[MAXN];
  // to store distance of
// all nodes from the source node
    static int[] dist = new int[MAXN];
 
    static class Pair<F, S> {
        F first;
        S second;
 
        public Pair(F first, S second) {
            this.first = first;
            this.second = second;
        }
    }
// Dijkstra's algorithm to find
// shortest path from source to node
    static void dijkstra(int source, int n) {
       // set all the vertices
    // distances as infinity
        Arrays.fill(dist, Integer.MAX_VALUE);
        boolean[] vis = new boolean[n];
 
    // make distance from source
    // vertex to source vertex is zero
        dist = 0;
          // // multiset do the job
    // as a min-priority queue
        PriorityQueue<Pair<Integer, Integer>> q = new PriorityQueue<>(Comparator.comparingInt(a -> a.first));
        q.add(new Pair<>(0, source));
 
        while (!q.isEmpty()) {
            Pair<Integer, Integer> p = q.poll();
            int x = p.second;
 
            if (vis[x])
                continue;
 
            vis[x] = true;
 
            for (Pair<Integer, Integer> e : v[x]) {
                int to = e.first;
                int w = e.second;
 
            // check if the next vertex
            // distance could be minimized
                if (dist[x] != Integer.MAX_VALUE && dist[x] + w < dist[to]) {
                    dist[to] = dist[x] + w;
                    q.add(new Pair<>(dist[to], to));
                }
            }
        }
    }
// function to add edges in graph
    static void addEdge(int s, int t, int weight) {
        v[s].add(new Pair<>(t, weight));
        v[t].add(new Pair<>(s, weight));
    }
 
    static int solve(int source, int destination, int intermediate, int n) {
        int ans = Integer.MAX_VALUE;
 
        dijkstra(source, n);
    // store distance from source to
    // all other vertices
        int[] dsource = Arrays.copyOf(dist, n);
 
        dijkstra(destination, n);
  // store distance from destination
    // to all other vertices
        int[] ddestination = Arrays.copyOf(dist, n);
 
        dijkstra(intermediate, n);
 // store distance from intermediate
    // to all other vertices
        int[] dintermediate = Arrays.copyOf(dist, n);
//Find the ans
        for (int i = 0; i < n; i++)
            ans = Math.min(ans, dsource[i] + ddestination[i] + dintermediate[i]);
 
        return ans;
    }
//Driver code
    public static void main(String[] args) {
 
        int n = 4;
        int source = 0, destination = 2, intermediate = 3;
 
        for (int i = 0; i < MAXN; i++)
            v[i] = new ArrayList<>();
 // add edges in graph
        addEdge(0, 1, 1);
        addEdge(1, 2, 2);
        addEdge(1, 3, 3);
 //function call
        System.out.println(solve(source, destination, intermediate, n));
    }
}


Python3




import sys
from collections import defaultdict
from heapq import heappop, heappush
 
# To store mapped values of graph
v = defaultdict(list)
 
# To store distance of all nodes from the source node
dist = {}
 
# Dijkstra's algorithm to find shortest path from source to node
def dijkstra(source, n):
    # Set all the vertices distances as infinity
    for i in range(n):
        dist[i] = sys.maxsize
 
    # Set all vertex as unvisited
    vis = [False] * n
 
    # Make distance from source vertex to source vertex is zero
    dist = 0
 
    # Use a min-priority queue (heap) to store vertices
    s = []
    heappush(s, (0, source))
 
    while s:
        # Pop the vertex with the minimum distance
        p = heappop(s)
        x = p[1]
        wei = p[0]
 
        # Check if the popped vertex is visited before
        if vis[x]:
            continue
 
        vis[x] = True
 
        for t, w in v[x]:
            # Check if the next vertex distance could be minimized
            if dist[x] + w < dist[t]:
                dist[t] = dist[x] + w
                # Insert the next vertex with the updated distance
                heappush(s, (dist[t], t))
 
# Function to add edges in graph
def add_edge(s, t, weight):
    v[s].append((t, weight))
    v[t].append((s, weight))
 
# Function to find the minimum shortest path
def solve(source, destination, intermediate, n):
    ans = sys.maxsize
 
    dijkstra(source, n)
 
    # Store distance from source to all other vertices
    dsource = {}
    for i in range(n):
        dsource[i] = dist[i]
 
    dijkstra(destination, n)
    # Store distance from destination to all other vertices
    ddestination = {}
    for i in range(n):
        ddestination[i] = dist[i]
 
    dijkstra(intermediate, n)
    # Store distance from intermediate to all other vertices
    dintermediate = {}
    for i in range(n):
        dintermediate[i] = dist[i]
 
    # Find required answer
    for i in range(n):
        ans = min(ans, dsource[i] + ddestination[i] + dintermediate[i])
 
    return ans
 
# Main code
if __name__ == '__main__':
    n = 4
    source = 0
    destination = 2
    intermediate = 3
 
    # Add edges in graph
    add_edge(0, 1, 1)
    add_edge(1, 2, 2)
    add_edge(1, 3, 3)
 
    # Function call for minimum shortest path
    print(solve(source, destination, intermediate, n))


C#




// C# program to find minimum distance between
// source and destination node and visiting
// of intermediate node is compulsory
 
using System;
using System.Collections.Generic;
 
public class GFG
{
 
 
static int MAXN = 100005;
 // to store mapped values of graph
static List<Pair<int, int>>[] v = new List<Pair<int, int>>[MAXN];
  // to store distance of
// all nodes from the source node
static int[] dist = new int[MAXN];
// Dijkstra's algorithm to find
// shortest path from source to node
static void dijkstra(int source, int n)
{
           // set all the vertices
    // distances as infinity
    Array.Fill(dist, int.MaxValue);
    bool[] vis = new bool[n];
     
    // make distance from source
    // vertex to source vertex is zero
    dist = 0;
       // // multiset do the job
    // as a min-priority queue
    SortedSet<Pair<int, int>> q = new SortedSet<Pair<int, int>>(Comparer<Pair<int, int>>.Create((a, b) => a.first.CompareTo(b.first)));
    q.Add(new Pair<int, int>(0, source));
 
    while (q.Count != 0)
    {
        Pair<int, int> p = q.Min;
        q.Remove(p);
        int x = p.second;
 
        if (vis[x])
            continue;
 
        vis[x] = true;
 
        foreach (Pair<int, int> e in v[x])
        {
            int to = e.first;
            int w = e.second;
    // check if the next vertex
            // distance could be minimized
            if (dist[x] != int.MaxValue && dist[x] + w < dist[to])
            {
                dist[to] = dist[x] + w;
                q.Add(new Pair<int, int>(dist[to], to));
            }
        }
    }
}
// function to add edges in graph
static void addEdge(int s, int t, int weight)
{
    v[s].Add(new Pair<int, int>(t, weight));
    v[t].Add(new Pair<int, int>(s, weight));
}
 
static int solve(int source, int destination, int intermediate, int n)
{
    int ans = int.MaxValue;
 
    dijkstra(source, n);
     // store distance from source to
    // all other vertices
    int[] dsource = (int[])dist.Clone();
 
    dijkstra(destination, n);
     // store distance from destination
    // to all other vertices
    int[] ddestination = (int[])dist.Clone();
 
    dijkstra(intermediate, n);
     // store distance from intermediate
    // to all other vertices
    int[] dintermediate = (int[])dist.Clone();
//Find the ans
    for (int i = 0; i < n; i++)
        ans = Math.Min(ans, dsource[i] + ddestination[i] + dintermediate[i]);
 
    return ans;
}
//Driver code
public static void Main(string[] args)
{
    int n = 4;
    int source = 0, destination = 2, intermediate = 3;
 
    for (int i = 0; i < MAXN; i++)
        v[i] = new List<Pair<int, int>>();
 
    addEdge(0, 1, 1);
    addEdge(1, 2, 2);
    addEdge(1, 3, 3);
 
    Console.WriteLine(solve(source, destination, intermediate, n));
}
 
class Pair<F, S>
{
    public F first;
    public S second;
 
    public Pair(F first, S second)
    {
        this.first = first;
        this.second = second;
    }
}
}


Javascript




// Define a constant MAXN and initialize arrays v and dist with its length
const MAXN = 100005;
 
// array of adjacency lists
let v = Array.from({ length: MAXN }, () => []);
// array to store the distances from the source vertex to all other vertices
let dist = Array(MAXN).fill(Infinity);
 
// Function to perform Dijkstra's algorithm on a given graph starting from a given source vertex
function dijkstra(source, n) {
  for (let i = 0; i < n; i++) {
    dist[i] = Infinity;
  }
    // Initialize a boolean array to track visited vertices
  let vis = Array(n).fill(false);
 
// Set the distance to the source vertex to 0 and add it to a set of vertices to be processed
  dist = 0;
  let s = new Set();
  s.add([0, source]);
 
  // Loop until there are no more vertices to process
  while (s.size > 0) {
    // Get the vertex with the smallest distance from the set
    let p = Array.from(s)[0];
    s.delete(p);
 
    // If the vertex has already been visited, skip it
    let x = p[1];
    let wei = p[0];
 
    if (vis[x]) {
      continue;
    }
 
    vis[x] = true;
     
// Loop through the adjacency list of the current vertex
    for (let i = 0; i < v[x].length; i++) {
      let e = v[x][i][0];// neighbor vertex index
      let w = v[x][i][1]; // weight of the edge connecting the current vertex and its neighbor
 
 
// If the distance to the neighbor vertex can be improved by going through the current vertex,
// update its distance and add it to the set of vertices to be processed
      if (dist[x] + w < dist[e]) {
        dist[e] = dist[x] + w;
        s.add([dist[e], e]);
      }
    }
  }
}
 
// Function to add an undirected edge between two vertices with a given weight
function add_edge(s, t, weight) {
  v[s].push([t, weight]);
  v[t].push([s, weight]);
}
 
// Function to solve the problem of finding the shortest path from source to destination that passes through an intermediate vertex
function solve(source, destination, intermediate, n) {
  let ans = Infinity;
 
// Run Dijkstra's algorithm from the source, destination, and intermediate vertices
  dijkstra(source, n);
  let dsource = [...dist];
 
  dijkstra(destination, n);
  let ddestination = [...dist];
 
  dijkstra(intermediate, n);
  let dintermediate = [...dist];
   
// Run Dijkstra's algorithm from the source, destination, and intermediate vertices
  for (let i = 0; i < n; i++) {
    ans = Math.min(ans, dsource[i] + ddestination[i] + dintermediate[i]);
  }
 
  return ans;
}
 
let n = 4;
let source = 0,
  destination = 2,
  intermediate = 3;
add_edge(0, 1, 1);
add_edge(1, 2, 2);
add_edge(1, 3, 3);
 
console.log(solve(source, destination, intermediate, n));


Output

6

Complexity Analysis:

  • Time complexity: O((N + M) * logN), where N is number of nodes, M is number of edges. 
  • Auxiliary Space: O(N+M) 


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