Open In App

Minimize cost to connect the graph by connecting any pairs of vertices having cost at least 0

Given a disconnected graph G with N vertices and M edges and an array cost[] corresponding to each vertex, the task is to find the minimum cost to make the graph by connecting any pairs of vertices having the cost of vertices at least 0 and the cost of connecting those pair of vertices is the sum of the cost of individual vertices. If it is impossible, then print “-1”.

Examples:



Input: N = 6, G[] = {{3, 1}, {2, 3}, {2, 1}, {4, 5}, {5, 6}, {6, 4}}, cost[] = {2, 1, 5, 3, 2, 9}
Output: 3
Explanation: The initial graph has two connected components – {1, 2, 3} and {4, 5, 6}. We can add an edge between 2 to 5 at a cost of cost[2] + cost[5] = 1 + 2 = 3. After adding this edge, the whole graph is connected.

Input: N = 6, G[] = {{3, 1}, {2, 3}, {2, 1}, {4, 5}, {5, 6}, {6, 4}}, cost[] = {2, 1, 5, -3, -2, -9}
Output: -1
Explanation: It is not possible to make the graph connected



Approach: The given problem can be solved using the Disjoint Set Union data structure. The idea is to store all the minimum values which are greater than or equals to 0, say minVal[] for all the different connected components, and check if any value in minVal[] is less than zero if it is true then print -1, Otherwise, find the minimum value in minVal[], say min, and find the sum of all the minimum values with the min value and print the answer.

Follow the below steps to solve the problem:

Below is the implementation of the above approach:




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to perform the find operation
// to find the parent of a disjoint set
int Find(vector<int>& parent, int a)
{
 
    return parent[a]
           = (parent[a] == a ? a : Find(parent, parent[a]));
}
 
// FUnction to perform union operation
// of disjoint set union
void Union(vector<int>& parent,
           vector<int>& rank,
           vector<int>& minVal,
           int a, int b)
{
 
    a = Find(parent, a);
    b = Find(parent, b);
 
    if (rank[a] == rank[b])
        rank[a]++;
 
    if (rank[a] > rank[b]) {
        parent[b] = a;
 
        // Update the minimum value
        // such than it should be
        // greater than 0
        if (minVal[a] >= 0
            && minVal[b] >= 0) {
            minVal[a] = min(minVal[a],
                            minVal[b]);
        }
        else if (minVal[a] >= 0
                 && minVal[b] < 0) {
            minVal[a] = minVal[a];
        }
        else if (minVal[a] < 0
                 && minVal[b] >= 0) {
            minVal[a] = minVal[b];
        }
        else {
            minVal[a] = max(minVal[a],
                            minVal[b]);
        }
    }
    else {
        parent[a] = b;
 
        // Update the minimum value
        // such than it should be
        // greater than 0
        if (minVal[a] >= 0
            && minVal[b] >= 0) {
            minVal[b] = min(minVal[a],
                            minVal[b]);
        }
        else if (minVal[a] >= 0
                 && minVal[b] < 0) {
            minVal[b] = minVal[a];
        }
        else if (minVal[a] < 0
                 && minVal[b] >= 0) {
            minVal[b] = minVal[b];
        }
        else {
            minVal[b] = max(minVal[a],
                            minVal[b]);
        }
    }
}
 
// Function to minimize the cost to
// make the graph connected as per
// the given condition
void findMinCost(vector<pair<int, int> >& G,
                 vector<int>& cost,
                 int N, int M)
{
 
    // Stores the parent elements of sets
    vector<int> parent(N + 1);
 
    // Stores the rank of the sets
    vector<int> rank(N + 1, 0);
 
    // Stores the minValue of the sets
    vector<int> minVal(N + 1);
 
    for (int i = 1; i < N + 1; i++) {
 
        // Update parent[i] to i
        parent[i] = i;
 
        // Update minValue[i] to cost[i-1]
        minVal[i] = cost[i - 1];
    }
 
    for (auto i : G) {
 
        // Add i.first and i.second
        // elements to the same set
        Union(parent, rank, minVal,
              i.first, i.second);
    }
 
    // Stores the parent elements of
    // the different components
    set<int> s;
 
    for (int i = 1; i < N + 1; i++) {
 
        // Insert parent of i to s
        s.insert(Find(parent, i));
    }
 
    // Stores the minimum value from s
    pair<int, int> min = { 0, INT_MAX };
 
    // Flag to mark if any minimum
    // value is negative
    bool flag = false;
 
    for (auto i : s) {
 
        // If minVal[i] is negative
        if (minVal[i] < 0) {
 
            // Mark flag as true
            flag = true;
        }
 
        if (min.second > minVal[i]) {
 
            // Update the minimum value
            min = { i, minVal[i] };
        }
    }
 
    // Stores minimum cost to add the edges
    int minCost = 0;
 
    // If the given graph is connected
    // or components minimum values not
    // having any negative edge
    if (!flag || (flag && s.size() == 1)) {
 
        for (auto i : s) {
 
            if (i != min.first) {
 
                // Update the minCost
                minCost += (minVal[i] + min.second);
            }
        }
 
        // Print the value of minCost
        cout << minCost << endl;
    }
    else {
 
        // Print -1
        cout << -1 << endl;
    }
}
 
// Driver Code
int main()
{
    int N = 6;
    vector<pair<int,int>> G = {
        { 3, 1 }, { 2, 3 }, { 2, 1 },
        { 4, 5 }, { 5, 6 }, { 6, 4 }
    };
    vector<int> cost{ 2, 1, 5, 3, 2, 9 };
    int M = G.size();
 
    findMinCost(G, cost, N, M);
 
    return 0;
}




// Java program for the above approach
import java.util.*;
 
class GFG{
    static class pair
    {
        int first, second;
        public pair(int first, int second) 
        {
            this.first = first;
            this.second = second;
        }   
    }
// Function to perform the find operation
// to find the parent of a disjoint set
static int Find(int[] parent, int a)
{
 
    return parent[a]
           = (parent[a] == a ? a : Find(parent, parent[a]));
}
 
// FUnction to perform union operation
// of disjoint set union
static void Union(int [] parent,
           int [] rank,
           int [] minVal,
           int a, int b)
{
 
    a = Find(parent, a);
    b = Find(parent, b);
 
    if (rank[a] == rank[b])
        rank[a]++;
 
    if (rank[a] > rank[b]) {
        parent[b] = a;
 
        // Update the minimum value
        // such than it should be
        // greater than 0
        if (minVal[a] >= 0
            && minVal[b] >= 0) {
            minVal[a] = Math.min(minVal[a],
                            minVal[b]);
        }
        else if (minVal[a] >= 0
                 && minVal[b] < 0) {
            minVal[a] = minVal[a];
        }
        else if (minVal[a] < 0
                 && minVal[b] >= 0) {
            minVal[a] = minVal[b];
        }
        else {
            minVal[a] = Math.max(minVal[a],
                            minVal[b]);
        }
    }
    else {
        parent[a] = b;
 
        // Update the minimum value
        // such than it should be
        // greater than 0
        if (minVal[a] >= 0
            && minVal[b] >= 0) {
            minVal[b] = Math.min(minVal[a],
                            minVal[b]);
        }
        else if (minVal[a] >= 0
                 && minVal[b] < 0) {
            minVal[b] = minVal[a];
        }
        else if (minVal[a] < 0
                 && minVal[b] >= 0) {
            minVal[b] = minVal[b];
        }
        else {
            minVal[b] = Math.max(minVal[a],
                            minVal[b]);
        }
    }
}
 
// Function to minimize the cost to
// make the graph connected as per
// the given condition
static void findMinCost(pair[] G,
                 int [] cost,
                 int N, int M)
{
 
    // Stores the parent elements of sets
    int [] parent = new int[N + 1];
 
    // Stores the rank of the sets
    int [] rank = new int[N + 1];
 
    // Stores the minValue of the sets
    int [] minVal = new int[N + 1];
 
    for (int i = 1; i < N + 1; i++) {
 
        // Update parent[i] to i
        parent[i] = i;
 
        // Update minValue[i] to cost[i-1]
        minVal[i] = cost[i - 1];
    }
 
    for (pair i : G) {
 
        // Add i.first and i.second
        // elements to the same set
        Union(parent, rank, minVal,
              i.first, i.second);
    }
 
    // Stores the parent elements of
    // the different components
    HashSet<Integer> s = new HashSet<Integer>();
 
    for (int i = 1; i < N + 1; i++) {
 
        // Insert parent of i to s
        s.add(Find(parent, i));
    }
 
    // Stores the minimum value from s
    pair min = new pair( 0, Integer.MAX_VALUE );
 
    // Flag to mark if any minimum
    // value is negative
    boolean flag = false;
 
    for (int i : s) {
 
        // If minVal[i] is negative
        if (minVal[i] < 0) {
 
            // Mark flag as true
            flag = true;
        }
 
        if (min.second > minVal[i]) {
 
            // Update the minimum value
            min = new pair( i, minVal[i] );
        }
    }
 
    // Stores minimum cost to add the edges
    int minCost = 0;
 
    // If the given graph is connected
    // or components minimum values not
    // having any negative edge
    if (!flag || (flag && s.size() == 1)) {
 
        for (int i : s) {
 
            if (i != min.first) {
 
                // Update the minCost
                minCost += (minVal[i] + min.second);
            }
        }
 
        // Print the value of minCost
        System.out.print(minCost +"\n");
    }
    else {
 
        // Print -1
        System.out.print(-1 +"\n");
    }
}
 
// Driver Code
public static void main(String[] args)
{
    int N = 6;
    pair []G = {
            new pair( 3, 1 ), new pair( 2, 3 ), new pair( 2, 1 ),
            new pair( 4, 5 ), new pair( 5, 6 ), new pair( 6, 4 )
    };
    int[] cost = { 2, 1, 5, 3, 2, 9 };
    int M = G.length;
 
    findMinCost(G, cost, N, M);
 
}
}
 
// This code is contributed by 29AjayKumar




# Python 3 program for the above approach
 
import sys
# Function to perform the find operation
# to find the parent of a disjoint set
def Find(parent, a):
    if parent[parent[a]] != parent[a]:
        parent[a]  = Find(parent, parent[a])
    return parent[a]
 
# FUnction to perform union operation
# of disjoint set union
def Union(parent, rank, minVal, a, b):
    a = Find(parent, a)
    b = Find(parent, b)
 
    if (rank[a] == rank[b]):
        rank[a] += 1
 
    if (rank[a] > rank[b]):
        parent[b] = a
 
        # Update the minimum value
        # such than it should be
        # greater than 0
        if (minVal[a] >= 0 and minVal[b] >= 0):
            minVal[a] = min(minVal[a],minVal[b])
        elif(minVal[a] >= 0 and minVal[b] < 0):
            minVal[a] = minVal[a]
        elif(minVal[a] < 0 and minVal[b] >= 0):
            minVal[a] = minVal[b]
        else:
            minVal[a] = max(minVal[a],minVal[b])
    else:
        parent[a] = b
 
        # Update the minimum value
        # such than it should be
        # greater than 0
        if (minVal[a] >= 0 and minVal[b] >= 0):
            minVal[b] = min(minVal[a],minVal[b])
        elif(minVal[a] >= 0 and minVal[b] < 0):
            minVal[b] = minVal[a]
        elif(minVal[a] < 0 and minVal[b] >= 0):
            minVal[b] = minVal[b]
        else:
            minVal[b] = max(minVal[a],minVal[b])
 
# Function to minimize the cost to
# make the graph connected as per
# the given condition
def findMinCost(G,cost,N, M):
    # Stores the parent elements of sets
    parent = [0 for i in range(N + 1)]
 
    # Stores the rank of the sets
    rank = [0 for i in range(N + 1)]
 
    # Stores the minValue of the sets
    minVal = [0 for i in range(N + 1)]
 
    for i in range(1,N + 1,1):
        # Update parent[i] to i
        parent[i] = i
         
        # Update minValue[i] to cost[i-1]
        minVal[i] = cost[i - 1]
 
    for i in G:
        # Add i.first and i.second
        # elements to the same set
        Union(parent, rank, minVal, i[0], i[1])
 
    # Stores the parent elements of
    # the different components
    s = set()
 
    for i in range(1,N + 1,1):
        # Insert parent of i to s
        s.add(Find(parent, i))
 
    # Stores the minimum value from s
    min1  = [0, sys.maxsize]
 
    # Flag to mark if any minimum
    # value is negative
    flag = False
 
    for i in s:
        # If minVal[i] is negative
        if (minVal[i] < 0):
 
            # Mark flag as true
            flag = True
 
        if (min1[1] > minVal[i]):
            # Update the minimum value
            min1 = [i, minVal[i]]
 
    # Stores minimum cost to add the edges
    minCost = 0
 
    # If the given graph is connected
    # or components minimum values not
    # having any negative edge
    if (flag == False or (flag and len(s) == 1)):
 
        for i in s:
            if (i != min1[0]):
 
                # Update the minCost
                minCost += (minVal[i] + min1[1])
 
        # Print the value of minCost
        print(minCost)
    else:
        # Print -1
        print(-1)
 
# Driver Code
if __name__ == '__main__':
    N = 6
    G = [[3, 1],[2, 3],[2, 1],[4, 5],[5, 6],[6, 4]]
    cost = [2, 1, 5, 3, 2, 9]
    M = len(G)
 
    findMinCost(G, cost, N, M)
     
    # This code is contributed by ipg2016107.




// C# program for the above approach
using System;
using System.Collections.Generic;
public class GFG{
    class pair
    {
        public int first, second;
        public pair(int first, int second) 
        {
            this.first = first;
            this.second = second;
        }   
    }
// Function to perform the find operation
// to find the parent of a disjoint set
static int Find(int[] parent, int a)
{
 
    return parent[a]
           = (parent[a] == a ? a : Find(parent, parent[a]));
}
 
// FUnction to perform union operation
// of disjoint set union
static void Union(int [] parent,
           int [] rank,
           int [] minVal,
           int a, int b)
{
 
    a = Find(parent, a);
    b = Find(parent, b);
 
    if (rank[a] == rank[b])
        rank[a]++;
 
    if (rank[a] > rank[b]) {
        parent[b] = a;
 
        // Update the minimum value
        // such than it should be
        // greater than 0
        if (minVal[a] >= 0
            && minVal[b] >= 0) {
            minVal[a] = Math.Min(minVal[a],
                            minVal[b]);
        }
        else if (minVal[a] >= 0
                 && minVal[b] < 0) {
            minVal[a] = minVal[a];
        }
        else if (minVal[a] < 0
                 && minVal[b] >= 0) {
            minVal[a] = minVal[b];
        }
        else {
            minVal[a] = Math.Max(minVal[a],
                            minVal[b]);
        }
    }
    else {
        parent[a] = b;
 
        // Update the minimum value
        // such than it should be
        // greater than 0
        if (minVal[a] >= 0
            && minVal[b] >= 0) {
            minVal[b] = Math.Min(minVal[a],
                            minVal[b]);
        }
        else if (minVal[a] >= 0
                 && minVal[b] < 0) {
            minVal[b] = minVal[a];
        }
        else if (minVal[a] < 0
                 && minVal[b] >= 0) {
            minVal[b] = minVal[b];
        }
        else {
            minVal[b] = Math.Max(minVal[a],
                            minVal[b]);
        }
    }
}
 
// Function to minimize the cost to
// make the graph connected as per
// the given condition
static void findMinCost(pair[] G,
                 int [] cost,
                 int N, int M)
{
 
    // Stores the parent elements of sets
    int [] parent = new int[N + 1];
 
    // Stores the rank of the sets
    int [] rank = new int[N + 1];
 
    // Stores the minValue of the sets
    int [] minVal = new int[N + 1];
 
    for (int i = 1; i < N + 1; i++) {
 
        // Update parent[i] to i
        parent[i] = i;
 
        // Update minValue[i] to cost[i-1]
        minVal[i] = cost[i - 1];
    }
 
    foreach (pair i in G) {
 
        // Add i.first and i.second
        // elements to the same set
        Union(parent, rank, minVal,
              i.first, i.second);
    }
 
    // Stores the parent elements of
    // the different components
    HashSet<int> s = new HashSet<int>();
 
    for (int i = 1; i < N + 1; i++) {
 
        // Insert parent of i to s
        s.Add(Find(parent, i));
    }
 
    // Stores the minimum value from s
    pair min = new pair( 0, int.MaxValue );
 
    // Flag to mark if any minimum
    // value is negative
    bool flag = false;
 
    foreach (int i in s) {
 
        // If minVal[i] is negative
        if (minVal[i] < 0) {
 
            // Mark flag as true
            flag = true;
        }
 
        if (min.second > minVal[i]) {
 
            // Update the minimum value
            min = new pair( i, minVal[i] );
        }
    }
 
    // Stores minimum cost to add the edges
    int minCost = 0;
 
    // If the given graph is connected
    // or components minimum values not
    // having any negative edge
    if (!flag || (flag && s.Count == 1)) {
 
        foreach (int i in s) {
 
            if (i != min.first) {
 
                // Update the minCost
                minCost += (minVal[i] + min.second);
            }
        }
 
        // Print the value of minCost
        Console.Write(minCost +"\n");
    }
    else {
 
        // Print -1
        Console.Write(-1 +"\n");
    }
}
 
// Driver Code
public static void Main(String[] args)
{
    int N = 6;
    pair []G = {
            new pair( 3, 1 ), new pair( 2, 3 ), new pair( 2, 1 ),
            new pair( 4, 5 ), new pair( 5, 6 ), new pair( 6, 4 )
    };
    int[] cost = { 2, 1, 5, 3, 2, 9 };
    int M = G.Length;
 
    findMinCost(G, cost, N, M);
 
}
}
 
 
 
// This code is contributed by 29AjayKumar




<script>
 
// JavaScript program for the above approach
 
// Function to perform the find operation
// to find the parent of a disjoint set
function Find(parent, a){
    if(parent[parent[a]] != parent[a])
        parent[a] = Find(parent, parent[a])
    return parent[a]
}
 
// Function to perform union operation
// of disjoint set union
function Union(parent, rank, minVal, a, b){
    a = Find(parent, a)
    b = Find(parent, b)
 
    if (rank[a] == rank[b])
        rank[a] += 1
 
    if (rank[a] > rank[b]){
        parent[b] = a
 
        // Update the minimum value
        // such than it should be
        // greater than 0
        if (minVal[a] >= 0 && minVal[b] >= 0)
            minVal[a] = Math.min(minVal[a],minVal[b])
        else if(minVal[a] >= 0 && minVal[b] < 0)
            minVal[a] = minVal[a]
        else if(minVal[a] < 0 && minVal[b] >= 0)
            minVal[a] = minVal[b]
        else
            minVal[a] = Math.max(minVal[a],minVal[b])
    }
    else{
        parent[a] = b
 
        // Update the minimum value
        // such than it should be
        // greater than 0
        if (minVal[a] >= 0 && minVal[b] >= 0)
            minVal[b] = Math.min(minVal[a],minVal[b])
        else if(minVal[a] >= 0 && minVal[b] < 0)
            minVal[b] = minVal[a]
        else if(minVal[a] < 0 && minVal[b] >= 0)
            minVal[b] = minVal[b]
        else
            minVal[b] = Math.max(minVal[a],minVal[b])
    }
}
 
// Function to minimize the cost to
// make the graph connected as per
// the given condition
function findMinCost(G,cost,N, M){
    // Stores the parent elements of sets
    let parent = new Array(N+1).fill(0)
 
    // Stores the rank of the sets
    let rank = new Array(N+1).fill(0)
 
    // Stores the minValue of the sets
    let minVal = new Array(N+1).fill(0)
 
    for(let i=1;i<N + 1;i++){
        // Update parent[i] to i
        parent[i] = i
         
        // Update minValue[i] to cost[i-1]
        minVal[i] = cost[i - 1]
    }
 
    for(let i of G)
        // Add i.first && i.second
        // elements to the same set
        Union(parent, rank, minVal, i[0], i[1])
 
    // Stores the parent elements of
    // the different components
    let s = new Set()
 
    for(let i=1;i<N + 1;i++)
        // Insert parent of i to s
        s.add(Find(parent, i))
 
    // Stores the minimum value from s
    let min1 = [0, Number.MAX_VALUE]
 
    // Flag to mark if any minimum
    // value is negative
    let flag = false
 
    for(let i of s){
        // If minVal[i] is negative
        if (minVal[i] <0)
 
            // Mark flag as true
            flag = true
 
        if (min1[1] > minVal[i])
            // Update the minimum value
            min1 = [i, minVal[i]]
    }
 
    // Stores minimum cost to add the edges
    let minCost = 0
 
    // If the given graph is connected
    // or components minimum values not
    // having any negative edge
    if (flag == false || (flag && s.length == 1)){
 
        for(let i of s){
            if (i != min1[0])
 
                // Update the minCost
                minCost += (minVal[i] + min1[1])
        }
 
        // Print the value of minCost
        document.write(minCost,"</0>")
    }
    else
        // Print -1
        document.write(-1,"</br>")
}
 
// Driver Code
 
let N = 6
let G = [[3, 1],[2, 3],[2, 1],[4, 5],[5, 6],[6, 4]]
let cost = [2, 1, 5, 3, 2, 9]
let M = G.length
 
findMinCost(G, cost, N, M)
 
// This code is contributed by shinjanpatra
 
</script>

 
 

Output: 
3

 

Time Complexity: O(N*log M)
Auxiliary Space: O(N) 


Article Tags :