📜  最低成本图

📅  最后修改于: 2021-10-25 03:21:33             🧑  作者: Mango

给定二维平面上的N 个节点,表示为(x i , y i ) 。如果节点之间的曼哈顿距离为1 ,则称这些节点已连接。您可以连接两个未连接的节点,代价是它们之间的欧氏距离。任务是连接图,使得每个节点都有一条来自任何节点的路径,成本最低。

例子:

方法:蛮力方法是将每个节点与每个其他节点连接起来,对于其他N 个节点也是如此,但在最坏的情况下,时间复杂度将为N N
另一种方法是找到每对具有欧几里德距离的顶点的成本,并且那些连接的顶点的成本为0
在知道每对的成本后,我们将对最小生成树应用 Kruskal 算法,它将产生连接图的最小成本。请注意,对于 Kruskal 算法,您必须了解不相交集联合 (DSU)。

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
 
// Max number of nodes given
const int N = 500 + 10;
 
// arr is the parent array
// sz is the size of the
// subtree in DSU
int arr[N], sz[N];
 
// Function to initialize the parent
// and size array for DSU
void initialize()
{
    for (int i = 1; i < N; ++i) {
        arr[i] = i;
        sz[i] = 1;
    }
}
 
// Function to return the
// parent of the node
int root(int i)
{
    while (arr[i] != i)
        i = arr[i];
    return i;
}
 
// Function to perform the
// merge operation
void unin(int a, int b)
{
    a = root(a);
    b = root(b);
 
    if (a != b) {
        if (sz[a] < sz[b])
            swap(a, b);
 
        sz[a] += sz[b];
        arr[b] = a;
    }
}
 
// Function to return the minimum cost required
double minCost(vector >& p)
{
 
    // Number of points
    int n = (int)p.size();
 
    // To store the cost of every possible pair
    // as { cost, {to, from}}.
    vector > > cost;
 
    // Calculating the cost of every possible pair
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if (i != j) {
 
                // Getting Manhattan distance
                int x = abs(p[i].first - p[j].first)
                        + abs(p[i].second - p[j].second);
 
                // If the distance is 1 the cost is 0
                // or already connected
                if (x == 1) {
                    cost.push_back({ 0, { i + 1, j + 1 } });
                    cost.push_back({ 0, { j + 1, i + 1 } });
                }
                else {
 
                    // Calculating the euclidean distance
                    int a = p[i].first - p[j].first;
                    int b = p[i].second - p[j].second;
                    a *= a;
                    b *= b;
                    double d = sqrt(a + b);
                    cost.push_back({ d, { i + 1, j + 1 } });
                    cost.push_back({ d, { j + 1, i + 1 } });
                }
            }
        }
    }
 
    // Krushkal Algorithm for Minimum
    // spanning tree
    sort(cost.begin(), cost.end());
 
    // To initialize the size and
    // parent array
    initialize();
 
    double ans = 0.00;
    for (auto i : cost) {
        double c = i.first;
        int a = i.second.first;
        int b = i.second.second;
 
        // If the parents are different
        if (root(a) != root(b)) {
            unin(a, b);
            ans += c;
        }
    }
 
    return ans;
}
 
// Driver code
int main()
{
 
    // Vector pairs of points
    vector > points = {
        { 1, 1 },
        { 2, 2 },
        { 2, 3 }
    };
 
    // Function calling and printing
    // the answer
    cout << minCost(points);
 
    return 0;
}


Java
// Java implementation of the approach
import java.util.*;
import java.lang.*;
import java.io.*;
 
class GFG{
     
// Max number of nodes given
static int N = 500 + 10;
 
static class pair
{
    double c;
    int first, second;
     
    pair(double c, int first, int second)
    {
        this.c = c;
        this.first = first;
        this.second = second;
    }
}
 
// arr is the parent array
// sz is the size of the
// subtree in DSU
static int[] arr = new int[N],
              sz = new int[N];
  
// Function to initialize the parent
// and size array for DSU
static void initialize()
{
    for(int i = 1; i < N; ++i)
    {
        arr[i] = i;
        sz[i] = 1;
    }
}
  
// Function to return the
// parent of the node
static int root(int i)
{
    while (arr[i] != i)
        i = arr[i];
         
    return i;
}
  
// Function to perform the
// merge operation
static void unin(int a, int b)
{
    a = root(a);
    b = root(b);
  
    if (a != b)
    {
        if (sz[a] < sz[b])
        {
            int tmp = a;
            a = b;
            b = tmp;
        }
         
        sz[a] += sz[b];
        arr[b] = a;
    }
}
  
// Function to return the minimum
// cost required
static double minCost(int[][] p)
{
     
    // Number of points
    int n = (int)p.length;
  
    // To store the cost of every possible pair
    // as { cost, {to, from}}.
    ArrayList cost = new ArrayList<>();
  
    // Calculating the cost of every possible pair
    for(int i = 0; i < n; ++i)
    {
        for(int j = 0; j < n; ++j)
        {
            if (i != j)
            {
                 
                // Getting Manhattan distance
                int x = Math.abs(p[i][0] - p[j][0]) +
                        Math.abs(p[i][1] - p[j][1]);
  
                // If the distance is 1 the cost is 0
                // or already connected
                if (x == 1)
                {
                    cost.add(new pair( 0, i + 1,
                                          j + 1 ));
                    cost.add(new pair( 0, j + 1,
                                          i + 1 ));
                }
                else
                {
                     
                    // Calculating the euclidean
                    // distance
                    int a = p[i][0] - p[j][0];
                    int b = p[i][1] - p[j][1];
                    a *= a;
                    b *= b;
                     
                    double d = Math.sqrt(a + b);
                    cost.add(new pair(d, i + 1,
                                         j + 1 ));
                    cost.add(new pair(d, j + 1,
                                         i + 1));
                }
            }
        }
    }
  
    // Krushkal Algorithm for Minimum
    // spanning tree
    Collections.sort(cost, new Comparator<>()
    {
        public int compare(pair a, pair b)
        {
            if(a.c <= b.c)
                return -1;
            else
                return 1;
        }
    });
  
    // To initialize the size and
    // parent array
    initialize();
  
    double ans = 0.00;
    for(pair i : cost)
    {
        double c = i.c;
        int a = i.first;
        int b = i.second;
  
        // If the parents are different
        if (root(a) != root(b))
        {
            unin(a, b);
            ans += c;
        }
    }
    return ans;
}
 
// Driver code
public static void main(String[] args)
{
     
    // Vector pairs of points
    int[][] points = { { 1, 1 },
                       { 2, 2 },
                       { 2, 3 }};
     
    // Function calling and printing
    // the answer
    System.out.format("%.5f", minCost(points));
}
}
 
// This code is contributed by offbeat


输出:
1.41421

时间复杂度: O(N*N)
辅助空间: O(N*N)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程