给定二维平面上的N 个节点,表示为(x i , y i ) 。如果节点之间的曼哈顿距离为1 ,则称这些节点已连接。您可以连接两个未连接的节点,代价是它们之间的欧氏距离。任务是连接图,使得每个节点都有一条来自任何节点的路径,成本最低。
例子:
Input: N = 3, edges[][] = {{1, 1}, {1, 1}, {2, 2}, {3, 2}}
Output: 1.41421
Since (2, 2) and (2, 3) are already connected.
So we try to connect either (1, 1) with (2, 2)
or (1, 1) with (2, 3) but (1, 1) with (2, 2)
yields the minimum cost.
Input: N = 3, edges[][] = {{1, 1}, {2, 2}, {3, 3}}
Output: 2.82843
方法:蛮力方法是将每个节点与每个其他节点连接起来,对于其他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 现场工作专业课程和学生竞争性编程现场课程。