Given a weighted undirected connected graph with N nodes and M edges. Some of the nodes are marked as good. The task is to find the shortest distance between any pair of two different good nodes.
Note: Nodes marked as yellow in the below examples are considered to be good nodes.
Examples:
Input :
Output : 7 Explanation : Pairs of Good Nodes and distance between them are: (1 to 3) -> distance: 7, (3 to 5) -> distance: 9, (1 to 5) -> distance: 16, out of which 7 is the minimum. Input :
Output : 4
Approach: Let us start by thinking of an algorithm to solve a simpler version of the given problem wherein all edges are of weight 1.
- Pick a random good node and perform a BFS from this point and stop at the first level say
which contains another good node. - We know that the minimum distance between any two good nodes can’t be more than s. So we again take a good node at random which is not already taken before and perform a BFS again. If we don’t find any special node in s distance, we terminate the search. If we do, then we update the value of s and repeat the procedure with some other special node taken at random.
We can apply a similar algorithm when weights are multiple.
Below is the implementation of the above approach:
// C++ program to find the shortest pairwise // distance between any two different good nodes. #include <bits/stdc++.h> using namespace std;
#define N 100005 const int MAXI = 99999999;
// Function to add edges void add_edge(vector<pair< int , int > > gr[], int x,
int y, int weight)
{ gr[x].push_back({ y, weight });
gr[y].push_back({ x, weight });
} // Function to find the shortest // distance between any pair of // two different good nodes int minDistance(vector<pair< int , int > > gr[], int n,
int dist[], int vis[], int a[], int k)
{ // Keeps minimum element on top
priority_queue<pair< int , int >, vector<pair< int , int > >,
greater<pair< int , int > > > q;
// To keep required answer
int ans = MAXI;
for ( int i = 1; i <= n; i++) {
// If it is not good vertex
if (!a[i])
continue ;
// Keep all vertices not visited
// and distance as MAXI
for ( int j = 1; j <= n; j++) {
dist[j] = MAXI;
vis[j] = 0;
}
// Distance from ith vertex to ith is zero
dist[i] = 0;
// Make queue empty
while (!q.empty())
q.pop();
// Push the ith vertex
q.push({ 0, i });
// Count the good vertices
int good = 0;
while (!q.empty()) {
// Take the top element
int v = q.top().second;
// Remove it
q.pop();
// If it is already visited
if (vis[v])
continue ;
vis[v] = 1;
// Count good vertices
good += a[v];
// If distance from vth vertex
// is greater than ans
if (dist[v] > ans)
break ;
// If two good vertices are found
if (good == 2 and a[v]) {
ans = min(ans, dist[v]);
break ;
}
// Go to all adjacent vertices
for ( int j = 0; j < gr[v].size(); j++) {
int to = gr[v][j].first;
int weight = gr[v][j].second;
// if distance is less
if (dist[v] + weight < dist[to]) {
dist[to] = dist[v] + weight;
q.push({ dist[to], to });
}
}
}
}
// Return the required answer
return ans;
} // Driver code int main()
{ // Number of vertices and edges
int n = 5, m = 5;
vector<pair< int , int > > gr[N];
// Function call to add edges
add_edge(gr, 1, 2, 3);
add_edge(gr, 1, 2, 3);
add_edge(gr, 2, 3, 4);
add_edge(gr, 3, 4, 1);
add_edge(gr, 4, 5, 8);
// Number of good nodes
int k = 3;
int a[N], vis[N], dist[N];
// To keep good vertices
a[1] = a[3] = a[5] = 1;
cout << minDistance(gr, n, dist, vis, a, k);
return 0;
} |
// Java program to find the shortest pairwise // distance between any two different good nodes. import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue;
class GFG{
static class Pair
{ int first, second;
public Pair( int first, int second)
{
this .first = first;
this .second = second;
}
public Pair()
{}
} static final int N = 100005 ;
static final int MAXI = 99999999 ;
// Function to add edges static void add_edge(ArrayList<Pair> gr[],
int x, int y, int weight)
{ gr[x].add( new Pair(y, weight));
gr[y].add( new Pair(x, weight));
} // Function to find the shortest // distance between any pair of // two different good nodes static int minDistance(ArrayList<Pair> gr[], int n,
int dist[], int vis[],
int a[], int k)
{ // Keeps minimum element on top
PriorityQueue<Pair> q = new PriorityQueue<>(
new Comparator<Pair>()
{
public int compare(Pair p1, Pair p2)
{
if (p1.first == p2.first)
{
return p1.second - p2.second;
}
return p1.first - p2.first;
}
});
// To keep required answer
int ans = MAXI;
for ( int i = 1 ; i <= n; i++)
{
// If it is not good vertex
if (a[i] == 0 )
continue ;
// Keep all vertices not visited
// and distance as MAXI
for ( int j = 1 ; j <= n; j++)
{
dist[j] = MAXI;
vis[j] = 0 ;
}
// Distance from ith vertex
// to ith is zero
dist[i] = 0 ;
// Make queue empty
while (!q.isEmpty())
q.poll();
// Push the ith vertex
q.add( new Pair( 0 , i));
// Count the good vertices
int good = 0 ;
while (!q.isEmpty())
{
// Take the top element
int v = q.peek().second;
// Remove it
q.poll();
// If it is already visited
if (vis[v] != 0 )
continue ;
vis[v] = 1 ;
// Count good vertices
good += a[v];
// If distance from vth vertex
// is greater than ans
if (dist[v] > ans)
break ;
// If two good vertices are found
if (good == 2 && a[v] != 0 )
{
ans = Math.min(ans, dist[v]);
break ;
}
// Go to all adjacent vertices
for ( int j = 0 ; j < gr[v].size(); j++)
{
int to = gr[v].get(j).first;
int weight = gr[v].get(j).second;
// If distance is less
if (dist[v] + weight < dist[to])
{
dist[to] = dist[v] + weight;
q.add( new Pair(dist[to], to));
}
}
}
}
// Return the required answer
return ans;
} // Driver code public static void main(String[] args)
{ // Number of vertices and edges
int n = 5 , m = 5 ;
@SuppressWarnings ( "unchecked" )
ArrayList<Pair>[] gr = new ArrayList[N];
for ( int i = 0 ; i < N; i++)
{
gr[i] = new ArrayList<Pair>();
}
// Function call to add edges
add_edge(gr, 1 , 2 , 3 );
add_edge(gr, 1 , 2 , 3 );
add_edge(gr, 2 , 3 , 4 );
add_edge(gr, 3 , 4 , 1 );
add_edge(gr, 4 , 5 , 8 );
// Number of good nodes
int k = 3 ;
int [] a = new int [N],
vis = new int [N],
dist = new int [N];
// To keep good vertices
a[ 1 ] = a[ 3 ] = a[ 5 ] = 1 ;
System.out.println(minDistance(
gr, n, dist, vis, a, k));
} } // This code is contributed by sanjeev2552 |
# Python3 program to find the shortest pairwise # distance between any two different good nodes. from heapq import *
N = 100005
MAXI = 99999999 ;
# Function to add edges def add_edge(gr, x, y, weight):
gr[x].append( (y, weight ));
gr[y].append((x, weight));
# Function to find the shortest # distance between any pair of # two different good nodes def minDistance(gr, n, dist, vis, a, k):
# Keeps minimum element on top
q = heapify([])
# To keep required answer
ans = MAXI;
for i in range ( 1 , n + 1 ):
# If it is not good vertex
if not (a[i]):
continue ;
# Keep all vertices not visited
# and distance as MAXI
for j in range ( 1 , n + 1 ):
dist[j] = MAXI;
vis[j] = 0 ;
# Distance from ith vertex to ith is zero
dist[i] = 0 ;
# Make queue empty
q = []
# Push the ith vertex
heappush(q, ( 0 , i ));
# Count the good vertices
good = 0 ;
while q:
# Take the top element
v = q[ 0 ][ 1 ]
# Remove it
heappop(q);
# If it is already visited
if (vis[v]):
continue ;
vis[v] = 1 ;
# Count good vertices
good + = a[v];
# If distance from vth vertex
# is greater than ans
if (dist[v] > ans):
break ;
# If two good vertices are found
if (good = = 2 and a[v]):
ans = min (ans, dist[v]);
break ;
# Go to all adjacent vertices
for j in range ( 0 , len (gr[v])):
to = gr[v][j][ 0 ];
weight = gr[v][j][ 1 ];
# if distance is less
if (dist[v] + weight < dist[to]):
dist[to] = dist[v] + weight;
heappush(q, (dist[to], to ));
# Return the required answer
return ans;
# Driver code # Number of vertices and edges n = 5
m = 5 ;
gr = [[] for _ in range (N)];
# Function call to add edges add_edge(gr, 1 , 2 , 3 );
add_edge(gr, 1 , 2 , 3 );
add_edge(gr, 2 , 3 , 4 );
add_edge(gr, 3 , 4 , 1 );
add_edge(gr, 4 , 5 , 8 );
# Number of good nodes k = 3 ;
a = [ 0 for _ in range (N)];
vis = [ None for _ in range (N)];
dist = [ None for _ in range (N)];
# To keep good vertices a[ 1 ] = 1
a[ 3 ] = 1
a[ 5 ] = 1 ;
print (minDistance(gr, n, dist, vis, a, k))
# This code is contributed by phasing17 |
// C# program to find the shortest pairwise // distance between any two different good nodes. using System;
using System.Linq;
using System.Collections.Generic;
class Pair
{ public int first, second;
public Pair( int first, int second)
{
this .first = first;
this .second = second;
}
public Pair()
{}
} class GFG{
static int N = 100005;
static int MAXI = 99999999;
// Function to add edges static void add_edge(List<Pair>[] gr,
int x, int y, int weight)
{ gr[x].Add( new Pair(y, weight));
gr[y].Add( new Pair(x, weight));
} // Function to find the shortest // distance between any pair of // two different good nodes static int minDistance(List<Pair>[] gr, int n,
int [] dist, int [] vis,
int [] a, int k)
{ // Keeps minimum element on top
List<Pair> q = new List<Pair>();
// To keep required answer
int ans = MAXI;
for ( int i = 1; i <= n; i++)
{
// If it is not good vertex
if (a[i] == 0)
continue ;
// Keep all vertices not visited
// and distance as MAXI
for ( int j = 1; j <= n; j++)
{
dist[j] = MAXI;
vis[j] = 0;
}
// Distance from ith vertex
// to ith is zero
dist[i] = 0;
// Make queue empty
q.Clear();
// Push the ith vertex
q.Add( new Pair(0, i));
// Count the good vertices
int good = 0;
while (q.Count > 0)
{
// Take the top element
int v = q[0].second;
// Remove it
q.RemoveAt(0);
// If it is already visited
if (vis[v] != 0)
continue ;
vis[v] = 1;
// Count good vertices
good += a[v];
// If distance from vth vertex
// is greater than ans
if (dist[v] > ans)
break ;
// If two good vertices are found
if (good == 2 && a[v] != 0)
{
ans = Math.Min(ans, dist[v]);
break ;
}
// Go to all adjacent vertices
for ( int j = 0; j < gr[v].Count; j++)
{
int to = gr[v][j].first;
int weight = gr[v][j].second;
// If distance is less
if (dist[v] + weight < dist[to])
{
dist[to] = dist[v] + weight;
q.Add( new Pair(dist[to], to));
q = q.OrderBy(p0 => p0.first).ThenBy(p0 => p0.second).ToList();
}
}
}
}
// Return the required answer
return ans;
} // Driver code public static void Main( string [] args)
{ // Number of vertices and edges
int n = 5;
List<Pair>[] gr = new List<Pair>[N];
for ( int i = 0; i < N; i++)
{
gr[i] = new List<Pair>();
}
// Function call to add edges
add_edge(gr, 1, 2, 3);
add_edge(gr, 1, 2, 3);
add_edge(gr, 2, 3, 4);
add_edge(gr, 3, 4, 1);
add_edge(gr, 4, 5, 8);
// Number of good nodes
int k = 3;
int [] a = new int [N],
vis = new int [N],
dist = new int [N];
// To keep good vertices
a[1] = a[3] = a[5] = 1;
Console.WriteLine(minDistance(
gr, n, dist, vis, a, k));
} } // This code is contributed by phasing17 |
// JS program to find the shortest pairwise // distance between any two different good nodes. let N = 100005 let MAXI = 99999999; // Function to add edges function add_edge(gr, x, y, weight)
{ gr[x].push([ y, weight ]);
gr[y].push([ x, weight ]);
} // Function to find the shortest // distance between any pair of // two different good nodes function minDistance(gr, n, dist, vis, a, k)
{ // Keeps minimum element on top
let q = [];
// To keep required answer
let ans = MAXI;
for ( var i = 1; i <= n; i++) {
// If it is not good vertex
if (a[i] != 0)
continue ;
// Keep all vertices not visited
// and distance as MAXI
for ( var j = 1; j <= n; j++) {
dist[j] = MAXI;
vis[j] = 0;
}
// Distance from ith vertex to ith is zero
dist[i] = 0;
// Make queue empty
while (q.length != 0)
q.pop();
// Push the ith vertex
q.push([0, i ]);
// Count the good vertices
let good = 0;
while (q.length != 0) {
// Take the top element
q.sort( function (a, b)
{
return (a[0] != b[0]) ? (a[0] > b[0]) : (a[1] > b[1])
})
let v = q[0][1];
// Remove it
q.shift();
// If it is already visited
if (vis[v] != 0)
continue ;
vis[v] = 1;
// Count good vertices
good += a[v];
// If distance from vth vertex
// is greater than ans
if (dist[v] > ans)
break ;
// If two good vertices are found
if (good == 2 && (a[v] != 0)) {
ans = Math.min(1 + ans,1 + dist[v]);
break ;
}
// Go to all adjacent vertices
for ( var j = 0; j < gr[v].length; j++) {
var to = gr[v][j][0];
var weight = gr[v][j][1] + 1;
// if distance is less
if (dist[v] + weight < dist[to]) {
dist[to] = dist[v] + weight + 1;
q.push([dist[to], to]);
}
}
}
}
// Return the required answer
return ans;
} // Driver code // Number of vertices and edges let n = 5, m = 5; let gr = new Array(N);
for ( var i = 0; i < N; i++)
gr[i] = []
// Function call to add edges add_edge(gr, 1, 2, 3); add_edge(gr, 1, 2, 3); add_edge(gr, 2, 3, 4); add_edge(gr, 3, 4, 1); add_edge(gr, 4, 5, 8); // Number of good nodes let k = 3; let a = new Array(N).fill(0)
let vis = new Array(N).fill(0)
let dist = new Array(N).fill(0);
// To keep good vertices a[1] = 1 a[3] = 1 a[5] = 1; console.log(minDistance(gr, n, dist, vis, a, k)); // This code is contributed by phasing17 |
Output:
7
Time complexity : O(V + E)
Here V is the number of vertices and E is the number of edges in the graph.
Space complexity : O(V+E)
The space complexity is mainly for the adjacency list used to represent the graph and the priority queue used to process the vertices.