📌  相关文章
📜  通过连接成本至少为 0 的任何顶点对来最小化连接图的成本

📅  最后修改于: 2022-05-13 01:56:08.937000             🧑  作者: Mango

通过连接成本至少为 0 的任何顶点对来最小化连接图的成本

给定一个有N个顶点和M条边的不连通图G以及一个数组cost[]对应于每个顶点,任务是通过连接任何顶点成本至少为 0的顶点对和连接这对顶点的成本是各个顶点成本的总和。如果不可能,则打印“-1”

例子:

方法:给定的问题可以使用不相交集联合数据结构来解决。这个想法是存储所有大于或等于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)