通过连接成本至少为 0 的任何顶点对来最小化连接图的成本
给定一个有N个顶点和M条边的不连通图G以及一个数组cost[]对应于每个顶点,任务是通过连接任何顶点成本至少为 0的顶点对和连接这对顶点的成本是各个顶点成本的总和。如果不可能,则打印“-1” 。
例子:
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
方法:给定的问题可以使用不相交集联合数据结构来解决。这个想法是存储所有大于或等于0的最小值,例如minVal[]用于所有不同的连接组件,并检查minVal[]中的任何值是否小于零,如果为真,则打印-1 , 否则,在minVal[]中找到最小值,例如min ,并找到所有最小值与最小值的总和并打印答案。
请按照以下步骤解决问题:
- 初始化一个向量minVal[]以找到每个集合的最小元素。
- 初始化向量parent(N+1), rank(N+1, 0), minVal(N+1) 。
- 初始化一个集合,比如s ,以存储每个集合的父级。
- 初始化一个变量,比如minCost ,它存储最小成本。
- 使用变量i遍历范围[1, N+1)并将parent[i]的值设置为I并将minVal[i]设置为cost[i – 1] 。
- 使用变量i遍历向量G并调用函数操作Union(parent, rank, minVal, i.first, i.second) 。
- 使用变量i遍历范围[1, N+1)并将I的父元素插入s 。
- 遍历集合s并找到s的最小值并将其存储在min中,如果任何值为负,则将flag 标记为 true。
- 如果给定的图已经连接或标志值为假,则:
- 使用变量I迭代s ,如果min值不等于I然后将 minCost 的值更新为minCost += (minVal[i] + min.second) 。
- 完成上述步骤后,打印minCost的值作为所得的最小成本。
- 否则,打印-1 。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to perform the find operation
// to find the parent of a disjoint set
int Find(vector& 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& parent,
vector& rank,
vector& 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 >& G,
vector& cost,
int N, int M)
{
// Stores the parent elements of sets
vector parent(N + 1);
// Stores the rank of the sets
vector rank(N + 1, 0);
// Stores the minValue of the sets
vector 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 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 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> G = {
{ 3, 1 }, { 2, 3 }, { 2, 1 },
{ 4, 5 }, { 5, 6 }, { 6, 4 }
};
vector cost{ 2, 1, 5, 3, 2, 9 };
int M = G.size();
findMinCost(G, cost, N, M);
return 0;
}
Java
// 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 s = new HashSet();
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
Python3
# 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#
// 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 s = new HashSet();
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
Javascript
3
时间复杂度: O(N*log M)
辅助空间: O(N)