Open In App

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

Last Updated : 01 Feb, 2023
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.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads