Skip to content
Related Articles

Related Articles

Minimize rope length to connect given points in a 3D plane

Improve Article
Save Article
  • Difficulty Level : Hard
  • Last Updated : 08 Nov, 2022
Improve Article
Save Article

Given a 2-D array A[][] of size N × 3, where each element of the array is of the form {x, y, z}, where x, y and z are coordinates of a point in 3D space. The task is to connect all the points such that the total length of the rope is minimized.

Note: The length of rope use to connect two points  A1(x1, y1, z1) and A2(x2, y2, z2) is given as: min( |x1-x2|, |y1-y2|, |z1-z2| )

Examples:

Input: A[][] = { {1, 2, 3}, {6, 8, 1}, {5, 3, 4}, {8, 5, 6} }
Output: 4
Explanation: Minimum edges use to connect all edge
Distance of P1 and P3 is 1.
Distance of P2 and P3 is 1.
Distance of P4 and P3 is 2.
Total length of rope used = 1 + 1 + 2 = 4

Input: A[][] = { {0, 5, 0}, {8, 5, 0}, {0, 1, 56} }
Output: 0
Explanation: Minimum edges use to connect all edge
Distance of P1 and P2 is 0.
Distance of P1 and P3 is 0. 
Total length of rope used = 0 + 0 = 0

Naive Approach: The basic idea is to connect all the points and form a graph. Then check all the possible combinations of edges and find the minimum among them.

Time Complexity: O(N^2CN) as there can be total N(N-1) edges and we will only need (N-1) edges from those to connect the graph.
Auxiliary Space: O(N)

Minimize rope cost to connect the points by using Minimum Spanning Tree

This problem can also be solved based on the minimum spanning tree (MST) concept. 

We will need to make a graph where the weight of each edge is the same as the distance between the points. The MST formed from that graph will have the minimum total distance among the points and so the required rope length will also be minimum.

Instead of connecting all the points we can build three separate graphs from the distances among the coordinates of each of the axis separately because of the special property of the distance. Consider those edges and use the concept of MST.

Follow the steps below to implement the idea:

  • Length of rope required to connect two points depends only on one axis whose difference is minimum.
  • So all the axis can be evaluated separately.
  • Sort all three coordinates separately.
  • Construct edges with edge weight equal to the difference of consecutive coordinates for all three axes separately.
  • Run the minimum spanning tree algorithm on the graph to find the minimum length of rope needed.

Code implementation of the above approach: 

C++




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
vector<vector<int> > edges;
 
int findparent(int a, vector<int>& parentOf)
{
    if (parentOf[a] == -1)
        return a;
    return parentOf[a] = findparent(parentOf[a], parentOf);
}
 
void union_set(int a, int b, vector<int>& parentOf,
               vector<int>& rank)
{
    int s1 = findparent(a, parentOf);
    int s2 = findparent(b, parentOf);
 
    if (s1 != s2) {
        int r1 = rank[s1];
        int r2 = rank[s2];
        if (r1 >= r2) {
            parentOf[s2] = s1;
            rank[s1] = r1 + r2;
        }
        else {
            parentOf[s1] = s2;
            rank[s2] = r1 + r2;
        }
    }
}
int calculatemst(int N)
{
    int cost = 0;
    vector<int> rank(N + 1, -1);
    vector<int> parentOf(N + 1, -1);
    for (int i = 0; i < edges.size(); i++) {
        int wt = edges[i][0], a = edges[i][1],
            b = edges[i][2];
        if (findparent(a, parentOf)
            != findparent(b, parentOf)) {
            cost += wt;
            union_set(a, b, parentOf, rank);
        }
    }
    return cost;
}
void graph(vector<pair<int, int> > v)
{
    for (int i = 0; i < v.size() - 1; i++) {
        int dist = v[i + 1].first - v[i].first;
        int nodeone = v[i].second;
        int nodesecond = v[i + 1].second;
        edges.push_back({ dist, nodeone, nodesecond });
    }
}
void solve(int a[][3], int N)
{
    vector<pair<int, int> > x, y, z;
    for (int i = 0; i < N; i++) {
        x.push_back({ a[i][0], i + 1 });
        y.push_back({ a[i][1], i + 1 });
        z.push_back({ a[i][2], i + 1 });
    }
    sort(x.begin(), x.end());
    sort(y.begin(), y.end());
    sort(z.begin(), z.end());
    graph(x);
    graph(y);
    graph(z);
    sort(edges.begin(), edges.end());
    return;
}
 
// Drivers code
int main()
{
    int arr[][3] = {
        { 1, 2, 3 }, { 6, 8, 1 }, { 5, 3, 4 }, { 8, 5, 6 }
    };
 
    // Function Call
    solve(arr, 4);
    cout << calculatemst(4) << endl;
}


Java




// Java code for the above approach:
import java.util.*;
 
class GFG {
  static ArrayList<ArrayList<Integer> > edges
    = new ArrayList<>();
 
  static int findparent(int a, int[] parentOf)
  {
    if (parentOf[a] == -1)
      return a;
    return parentOf[a]
      = findparent(parentOf[a], parentOf);
  }
 
  static void union_set(int a, int b, int[] parentOf,
                        int[] rank)
  {
    int s1 = findparent(a, parentOf);
    int s2 = findparent(b, parentOf);
 
    if (s1 != s2) {
      int r1 = rank[s1];
      int r2 = rank[s2];
      if (r1 >= r2) {
        parentOf[s2] = s1;
        rank[s1] = r1 + r2;
      }
      else {
        parentOf[s1] = s2;
        rank[s2] = r1 + r2;
      }
    }
  }
  static int calculatemst(int N)
  {
    int cost = 0;
    int[] rank = new int[N + 1];
    int[] parentOf = new int[N + 1];
    Arrays.fill(rank, -1);
    Arrays.fill(parentOf, -1);
 
    for (int i = 0; i < edges.size(); i++) {
      int wt = edges.get(i).get(0);
      int a = edges.get(i).get(1);
      int b = edges.get(i).get(2);
      if (findparent(a, parentOf)
          != findparent(b, parentOf)) {
        cost += wt;
        union_set(a, b, parentOf, rank);
      }
    }
    return cost;
  }
  static void graph(ArrayList<pair> v)
  {
    for (int i = 0; i < v.size() - 1; i++) {
      int dist = v.get(i + 1).first - v.get(i).first;
      int nodeone = v.get(i).second;
      int nodesecond = v.get(i + 1).second;
      ArrayList<Integer> al = new ArrayList<>();
      al.add(dist);
      al.add(nodeone);
      al.add(nodesecond);
      edges.add(al);
    }
  }
  static void solve(int a[][], int N)
  {
    ArrayList<pair> x = new ArrayList<>();
    ArrayList<pair> y = new ArrayList<>();
    ArrayList<pair> z = new ArrayList<>();
    for (int i = 0; i < N; i++) {
      x.add(new pair(a[i][0], i + 1));
      y.add(new pair(a[i][1], i + 1));
      z.add(new pair(a[i][2], i + 1));
    }
    Collections.sort(x, (pair A, pair B) -> {
      return A.first - B.first;
    });
    Collections.sort(y, (pair A, pair B) -> {
      return A.first - B.first;
    });
    Collections.sort(z, (pair A, pair B) -> {
      return A.first - B.first;
    });
    graph(x);
    graph(y);
    graph(z);
    Collections.sort(edges,
                     (ArrayList<Integer> A,
                      ArrayList<Integer> B) -> {
                       return A.get(0) - B.get(0);
                     });
    return;
  }
  static class pair {
    int first;
    int second;
    pair(int a, int b)
    {
      first = a;
      second = b;
    }
  }
 
  // Driver code
  public static void main(String[] args)
  {
    int arr[][] = { { 1, 2, 3 },
                   { 6, 8, 1 },
                   { 5, 3, 4 },
                   { 8, 5, 6 } };
 
    // Function Call
    solve(arr, 4);
    System.out.println(calculatemst(4));
  }
}
 
// This code is contributed by karandeep1234.


Python3




# Python code for the above approach\
edges = []
 
def findparent(a, parentOf):
    if (parentOf[a] == -1):
        return a
    parentOf[a] = findparent(parentOf[a], parentOf)
    return parentOf[a]
 
def union_set(a, b, parentOf, rank):
    s1 = findparent(a, parentOf)
    s2 = findparent(b, parentOf)
 
    if (s1 != s2):
        r1 = rank[s1]
        r2 = rank[s2]
        if (r1 >= r2):
            parentOf[s2] = s1
            rank[s1] = r1 + r2
        else:
            parentOf[s1] = s2
            rank[s2] = r1 + r2
 
def calculatemst(N):
    cost = 0
    rank = [-1] * (N + 1)
    parentOf = [-1] * (N + 1)
    for i in range(len(edges)):
        wt = edges[i][0]
        a = edges[i][1]
        b = edges[i][2]
        if (findparent(a, parentOf) != findparent(b, parentOf)):
            cost += wt
            union_set(a, b, parentOf, rank)
 
    return cost
 
def graph(v):
    for i in range(len(v) - 1):
        dist = v[i + 1][0] - v[i][0]
        nodeone = v[i][1]
        nodesecond = v[i + 1][1]
        edges.append([dist, nodeone, nodesecond])
 
def solve(a, N):
    x = []
    y = []
    z = []
    for i in range(N):
        x.append([a[i][0], i + 1])
        y.append([a[i][1], i + 1])
        z.append([a[i][2], i + 1])
 
    x.sort()
    y.sort()
    z.sort()
    graph(x)
    graph(y)
    graph(z)
    edges.sort()
    return
 
# Drivers code
arr = [[1, 2, 3], [6, 8, 1], [5, 3, 4], [8, 5, 6]]
 
# Function Call
solve(arr, 4)
print(calculatemst(4))
 
# This code is contributed by Saurabh Jaiswal


Javascript




<script>
        // JavaScript code for the above approach
        let edges = [];
 
        function findparent(a, parentOf) {
            if (parentOf[a] == -1)
                return a;
            return parentOf[a] = findparent(parentOf[a], parentOf);
        }
 
        function union_set(a, b, parentOf,
            rank) {
            let s1 = findparent(a, parentOf);
            let s2 = findparent(b, parentOf);
 
            if (s1 != s2) {
                let r1 = rank[s1];
                let r2 = rank[s2];
                if (r1 >= r2) {
                    parentOf[s2] = s1;
                    rank[s1] = r1 + r2;
                }
                else {
                    parentOf[s1] = s2;
                    rank[s2] = r1 + r2;
                }
            }
        }
        function calculatemst(N) {
            let cost = 0;
            let rank = new Array(N + 1).fill(-1);
            let parentOf = new Array(N + 1).fill(-1);
            for (let i = 0; i < edges.length; i++) {
                let wt = edges[i][0], a = edges[i][1],
                    b = edges[i][2];
                if (findparent(a, parentOf)
                    != findparent(b, parentOf)) {
                    cost += wt;
                    union_set(a, b, parentOf, rank);
                }
            }
            return cost;
        }
        function graph(v) {
            for (let i = 0; i < v.length - 1; i++) {
                let dist = v[i + 1][0] - v[i][0];
                let nodeone = v[i][1];
                let nodesecond = v[i + 1][1];
                edges.push([dist, nodeone, nodesecond]);
            }
        }
        function solve(a, N) {
            let x = [], y = [], z = [];
            for (let i = 0; i < N; i++) {
                x.push([a[i][0], i + 1]);
                y.push([a[i][1], i + 1]);
                z.push([a[i][2], i + 1]);
            }
            x.sort(function (a, b) { return a[0] - b[0] });
            y.sort(function (a, b) { return a[0] - b[0] });
            z.sort(function (a, b) { return a[0] - b[0] });
            graph(x);
            graph(y);
            graph(z);
            edges.sort(function (a, b) { return a[0] - b[0] })
            return;
        }
 
        // Drivers code
        let arr = [
            [1, 2, 3], [6, 8, 1], [5, 3, 4], [8, 5, 6]
        ];
 
        // Function Call
        solve(arr, 4);
        document.write(calculatemst(4));
 
 // This code is contributed by Potta Lokesh
 
    </script>


Output

4

Time complexity: O(N * log N)
Auxiliary Space: O(N)


My Personal Notes arrow_drop_up
Related Articles

Start Your Coding Journey Now!