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: 6
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: 3
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.
// 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;
} |
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));
}
} |
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# 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;
}
} } |
// 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)); |
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)