Open In App

Find the shortest distance between any pair of two different good nodes

Improve
Improve
Like Article
Like
Save
Share
Report

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 s         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++

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

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

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

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

                    

Javascript

// 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.



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