1+ class Edge {
2+ public int source ;
3+ public int destination ;
4+ public int weight ; // manhattan distance
5+
6+ public Edge (int s , int d , int w ){
7+ this .source = s ;
8+ this .destination = d ;
9+ this .weight = w ;
10+ }
11+
12+ @ Override
13+ public String toString () {
14+ return "Edge(u=" + source + ", v=" + destination + ", w=" + weight + ")" ;
15+ }
16+ }
17+
18+ class DisjointSet {
19+ private int [] roots ;
20+ private int [] ranks ;
21+
22+ public DisjointSet (int n ) {
23+ this .roots = new int [n ];
24+ this .ranks = new int [n ];
25+
26+ // intializing
27+ for (int i =0 ; i <n ; i ++){
28+ this .roots [i ] = i ;
29+ this .ranks [i ] = 0 ; // initially ranking 0
30+ }
31+ }
32+
33+ // get the root, use path compression
34+ public int find (int u ) {
35+ if (this .roots [u ] == u )
36+ return u ;
37+
38+ int root = find (this .roots [u ]);
39+ this .roots [u ] = root ;
40+ return root ;
41+ }
42+
43+ // use ranking
44+ public void union (int x , int y ) {
45+ int rootX = find (x ), rootY = find (y );
46+ int rankX = this .ranks [rootX ], rankY = this .ranks [rootY ];
47+
48+ if (rootX == rootY ) // already same roots
49+ return ;
50+
51+ if (rankX < rankY ){
52+ // put into rootY
53+ this .roots [rootX ] = this .roots [rootY ];
54+ this .ranks [rootY ]++;
55+ }
56+ else {
57+ // default, put into rootX
58+ this .roots [rootY ] = this .roots [rootX ];
59+ this .ranks [rootX ]++;
60+ }
61+ }
62+
63+ public boolean areDisjoint (int u , int v ) {
64+ return (find (u ) != find (v ));
65+ }
66+ }
67+
68+ class Solution {
69+ private int getManhattanDistance (int [] p1 , int [] p2 ){
70+ return (
71+ Math .abs (p1 [0 ] - p2 [0 ]) +
72+ Math .abs (p1 [1 ] - p2 [1 ])
73+ );
74+ }
75+
76+ private List <Edge > getEdges (int [][] points ) {
77+ int n = points .length ;
78+ List <Edge > edges = new ArrayList <>();
79+
80+ // edge case
81+ if (n <= 1 )
82+ return edges ;
83+
84+ for (int i =0 ; i <(n - 1 ); i ++){
85+ for (int j =i +1 ; j <n ; j ++){
86+ int w = getManhattanDistance (points [i ], points [j ]);
87+ edges .add (new Edge (i , j , w ));
88+ }
89+ }
90+
91+ return edges ;
92+ }
93+
94+ private boolean isEdgeCase (int [][] points ) {
95+ return (points .length <= 1 );
96+ }
97+
98+ private int getCostMST (List <Edge > edges , int numVertices ) {
99+ DisjointSet ds = new DisjointSet (numVertices );
100+ int minCost = 0 , numEdgesTaken = 0 ;
101+
102+ for (Edge edge : edges ){
103+ if (ds .areDisjoint (edge .source , edge .destination )){
104+ ds .union (edge .source , edge .destination );
105+ numEdgesTaken ++;
106+ minCost += edge .weight ;
107+ }
108+
109+ if (numEdgesTaken == (numVertices - 1 )) // tree is formed, early exit
110+ break ;
111+ }
112+ return minCost ;
113+ }
114+
115+ public int minCostConnectPoints (int [][] points ) {
116+ // edge cases
117+ if (isEdgeCase (points ))
118+ return 0 ;
119+
120+ // edges
121+ List <Edge > edges = getEdges (points );
122+
123+ // sort the edges in ascending order
124+ edges .sort ((x1 , x2 ) -> (x1 .weight - x2 .weight ));
125+
126+ // Kruskals algorithm for MST [Union Find]
127+ return getCostMST (edges , points .length );
128+ }
129+ }
0 commit comments