Min Cost to Connect All Points

You are given an array points representing integer coordinates of some points on a 2D-plane, where points[i] = [xi, yi].

The cost of connecting two points [xi, yi] and [xj, yj] is the manhattan distance between them: |xi - xj| + |yi - yj|, where |val| denotes the absolute value of val.

Return the minimum cost to make all points connected. All points are connected if there is exactly one simple path between any two points.

Example 1:

Input: points = [[0,0],[2,2],[3,10],[5,2],[7,0]]
Output: 20
Explanation:

We can connect the points as shown above to get the minimum cost of 20.
Notice that there is a unique path between every pair of points.

Example 2:

Input: points = [[3,12],[-2,5],[-4,1]]
Output: 18

思路:这题跟 1135 Connecting Cities With Minimum Cost 一模一样,就是抽象化的minimum spanning tree, 每次用最小的边去connect graph;Union Find 直觉解决问题;

class Solution {
    private class Connection {
        public int from;
        public int to;
        public int cost;
        public Connection(int from, int to, int cost) {
            this.from = from;
            this.to = to;
            this.cost = cost;
        }
    }
    
    private class UnionFind {
        private int[] father;
        private int size;
        public UnionFind(int n) {
            this.father = new int[n + 1];
            for(int i = 0; i <= n; i++) {
                father[i] = i;
            }
            this.size = n;
        }
        
        public int find(int x) {
            int j = x;
            while(father[j] != j) {
                j = father[j];
            }
            // path compression;
            while(x != j) {
                int fx = father[x];
                father[x] = j;
                x = fx;
            }
            return j;
        }
        
        public void union(int a, int b) {
            int root_a = find(a);
            int root_b = find(b);
            if(root_a != root_b) {
                father[root_a] = root_b;
                size--;
            }
        }
        
        public int getSize() {
            return this.size;
        }
    }
    
    public int minCostConnectPoints(int[][] points) {
        List<Connection> clist = new ArrayList<Connection>();
        int n = points.length;
        for(int i = 0; i < n; i++) {
            for(int j = i + 1; j < n; j++) {
                clist.add(new Connection(i, j, 
                                         getCost(points[i][0], points[i][1], points[j][0], points[j][1])));
            }
        }
        Collections.sort(clist, (a, b) -> (a.cost - b.cost));
        UnionFind uf = new UnionFind(n);
        int totalcost = 0;
        for(Connection connection: clist) {
            int a = connection.from;
            int b = connection.to;
            int cost = connection.cost;
            if(uf.find(a) != uf.find(b)) {
                uf.union(a, b);
                totalcost += cost;
            }
        }
        return totalcost;
    }
    
    private int getCost(int x1, int y1, int x2, int y2) {
        return Math.abs(x1 - x2) + Math.abs(y1 - y2);
    }
}

 思路2: 这题也可以用dijkstra来做,一个node,可以connect到别的node,可以有N条边,那么就是HashMap<Integer, List<Node>> Node里面存 id, cost,然后把所有的neighbor全部丢到priorityqueue里面按照cost sort,然后每次出来都是neighbor cost最小的,visited来收集node的id,这样把每条边都跑完,也就收集到了所有的node id,形成的cost就是最小的visit path cost;

class Solution {
    private class Node {
        public int index;
        public int cost;
        public Node(int index, int cost) {
            this.index = index;
            this.cost = cost;
        }
    }
    
    public int minCostConnectPoints(int[][] points) {
        HashMap<Integer, List<Node>> graph = new HashMap<>();
        int n = points.length;
        for(int i = 0; i < n; i++) {
            for(int j = i + 1; j < n; j++) {
                int from = i;
                int to = j;
                int cost = getCost(points[i][0], points[i][1], points[j][0], points[j][1]);
                graph.putIfAbsent(from, new ArrayList<Node>());
                graph.putIfAbsent(to, new ArrayList<Node>());
                graph.get(from).add(new Node(to, cost));
                graph.get(to).add(new Node(from, cost));
            }
        }
        
        PriorityQueue<Node> pq = new PriorityQueue<Node>((a, b) -> (a.cost - b.cost));
        pq.offer(new Node(0, 0));
        HashSet<Integer> visited = new HashSet<Integer>();
        
        int totalcost = 0;
        while(!pq.isEmpty()) {
            Node node = pq.poll();
            if(visited.contains(node.index)) {
                continue;
            }
            visited.add(node.index);
            totalcost += node.cost;
            
            if(graph.get(node.index) != null) {
                for(Node neighbor: graph.get(node.index)) {
                    if(!visited.contains(neighbor.index)) {
                        pq.offer(neighbor);
                    }
                }
            }
        }
        return totalcost;
    }
    
    private int getCost(int x1, int y1, int x2, int y2) {
        return Math.abs(x1 - x2) + Math.abs(y1 - y2);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值