Given N nodes on a 2-D plane represented as (xi, yi). The nodes are said to be connected if the manhattan distance between them is 1. You can connect two nodes that are not connected at the cost of euclidean distance between them. The task is to connect the graph such that every node has a path from any node with minimum cost.
Examples:
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
Approach: The brute force approach is to connect each node with every other node and similarly for the other N nodes but in the worst case the time complexity will be NN.
The other way is to find the cost of every pair of vertices with the euclidean distance and those pairs which are connected will have the cost as 0.
After knowing the cost of each pair we will apply the Kruskal Algorithm for the minimum spanning tree and it will yield the minimum cost for connecting the graph. Note that for Kruskal Algorithm, you have to have the knowledge of Disjoint Set Union (DSU).
Below is the implementation of the above approach:
// C++ implementation of the approach #include <bits/stdc++.h> 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 Union( 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<pair< int , int > >& p)
{ // Number of points
int n = ( int )p.size();
// To store the cost of every possible pair
// as { cost, {to, from}}.
vector<pair< double , pair< int , int > > > 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)) {
Union(a, b);
ans += c;
}
}
return ans;
} // Driver code int main()
{ // Vector pairs of points
vector<pair< int , int > > points = {
{ 1, 1 },
{ 2, 2 },
{ 2, 3 }
};
// Function calling and printing
// the answer
cout << minCost(points);
return 0;
} |
// 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 union( 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<pair> 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))
{
union(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 |
# Python3 implementation of the approach # Max number of nodes given N = 500 + 10
# arr is the parent array # sz is the size of the # subtree in DSU arr = [i for i in range (N)]
sz = [ 0 ] * N
# Function to return the # parent of the node def root(i):
while arr[i] ! = i:
i = arr[i]
return i
# Function to perform the # merge operation def Union(a, b):
a = root(a)
b = root(b)
if a ! = b:
if sz[a] < sz[b]:
a, b = b, a
sz[a] + = sz[b]
arr[b] = a
# Function to return the minimum cost required def minCost():
global points
# Number of points
n = len (points)
# To store the cost of every possible pair
# as : cost, :to, from.
cost = []
# Calculating the cost of every possible pair
for i in range (n):
for j in range (n):
if i ! = j:
# Getting Manhattan distance
x = abs (points[i][ 0 ] - points[j][ 0 ]) + abs (points[i][ 1 ] - points[j][ 1 ])
# If the distance is 1 the cost is 0
# or already connected
if x = = 1 :
cost.append(( 0 , (i + 1 , j + 1 )))
cost.append(( 0 , (j + 1 , i + 1 )))
else :
# Calculating the euclidean distance
a = points[i][ 0 ] - points[j][ 0 ]
b = points[i][ 1 ] - points[j][ 1 ]
a * = a
b * = b
d = (a + b) * * 0.5
cost.append((d, (i + 1 , j + 1 )))
cost.append((d, (j + 1 , i + 1 )))
# Krushkal Algorithm for Minimum
# spanning tree
cost.sort()
ans = 0.00
for i in cost:
c = i[ 0 ]
a = i[ 1 ][ 0 ]
b = i[ 1 ][ 1 ]
# If the parents are different
if root(a) ! = root(b):
Union(a, b)
ans + = c
return ans
# Driver code if __name__ = = "__main__" :
# Vector pairs of points
points = [( 1 , 1 ), ( 2 , 2 ), ( 2 , 3 )]
# Function calling and printing
# the answer
print (minCost())
|
// C# implementation of the approach using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{ // Max number of nodes given
static int N = 500 + 10;
// arr is the parent array
// sz is the size of the
// subtree in DSU
static int [] arr = Enumerable.Range(0, N).ToArray();
static int [] sz = new int [N];
// 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 Union( int a, int b)
{
a = root(a);
b = root(b);
if (a != b)
{
if (sz[a] < sz[b])
{
(a, b) = (b, a);
}
sz[a] += sz[b];
arr[b] = a;
}
}
// Function to return the minimum cost required
static double minCost()
{
var points = new List<( int , int )>
{
(1, 1), (2, 2), (2, 3)
};
// Number of points
int n = points.Count;
// To store the cost of every possible pair
// as : cost, :to, from.
var cost = new List<( double , ( int , int ))>();
// 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(points[i].Item1 - points[j].Item1) + Math.Abs(points[i].Item2 - points[j].Item2);
// If the distance is 1 the cost is 0
// or already connected
if (x == 1)
{
cost.Add((0, (i + 1, j + 1)));
cost.Add((0, (j + 1, i + 1)));
}
else
{
// Calculating the euclidean distance
int a = points[i].Item1 - points[j].Item1;
int b = points[i].Item2 - points[j].Item2;
a *= a;
b *= b;
double d = Math.Sqrt(a + b);
cost.Add((d, (i + 1, j + 1)));
cost.Add((d, (j + 1, i + 1)));
}
}
}
}
// Krushkal Algorithm for Minimum
// spanning tree
cost.Sort();
double ans = 0.00;
foreach ( var i in cost)
{
double c = i.Item1;
int a = i.Item2.Item1;
int b = i.Item2.Item2;
// If the parents are different
if (root(a) != root(b))
{
Union(a, b);
ans += c;
}
}
return ans;
}
// Driver code
static void Main( string [] args)
{
Console.WriteLine(minCost());
}
} // This code is contributed by shiv1o43g |
// Max number of nodes given const N = 500 + 10; // arr is the parent array // sz is the size of the // subtree in DSU let arr = []; for (let i = 0; i < N; i++) {
arr[i] = i;
} let sz = Array(N).fill(0); // Function to return the // parent of the node function root(i) {
while (arr[i] !== i) {
i = arr[i];
}
return i;
} // Function to perform the // merge operation function Union(a, b) {
a = root(a);
b = root(b);
if (a !== b) {
if (sz[a] < sz[b]) {
[a, b] = [b, a];
}
sz[a] += sz[b];
arr[b] = a;
}
} // Function to return the minimum cost required function minCost(points) {
// Number of points
let n = points.length;
// To store the cost of every possible pair
// as : cost, :to, from.
let cost = [];
// Calculating the cost of every possible pair
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
if (i !== j) {
// Getting Manhattan distance
let x = Math.abs(points[i][0] - points[j][0]) + Math.abs(points[i][1] - points[j][1]);
// If the distance is 1 the cost is 0
// or already connected
if (x === 1) {
cost.push([0, [i + 1, j + 1]]);
cost.push([0, [j + 1, i + 1]]);
} else {
// Calculating the euclidean distance
let a = points[i][0] - points[j][0];
let b = points[i][1] - points[j][1];
a *= a;
b *= b;
let d = Math.sqrt(a + b);
cost.push([d, [i + 1, j + 1]]);
cost.push([d, [j + 1, i + 1]]);
}
}
}
}
// Krushkal Algorithm for Minimum
// spanning tree
cost.sort((a, b) => a[0] - b[0]);
let ans = 0.0;
for (let i = 0; i < cost.length; i++) {
let c = cost[i][0];
let a = cost[i][1][0];
let b = cost[i][1][1];
// If the parents are different
if (root(a) !== root(b)) {
Union(a, b);
ans += c;
}
}
return ans;
} // Driver code // Vector pairs of points
const points = [[1, 1], [2, 2], [2, 3]];
// Function calling and printing the answer
console.log(minCost(points).toFixed(5));
|
1.41421
Time Complexity: O(N*N)
Auxiliary Space: O(N*N)