Kruskal 算法《图算法》

  1. 连接所有点的最小费用

问题拆解:size个顶点求最小生成树(无向图)
思路:
先模拟,将所有边加入到edges 中,按照weight权值排序(从小到大),之后依次遍历已排序的边,加入该边,判断是否与当前的图结构成环(并查集判环),否则加入该边,是则continue,直到加入了size-1条边为止跳出循环

class Solution {
    public int minCostConnectPoints(int[][] points) {
        int size = points.length;  //size个点,抽象为各个点,下标为0开始
        LinkedList<Node> edges = new LinkedList<>();
        for(int i=0;i<size;i++){
            for(int j=i+1;j<size;j++){  //后面的点
                //存储所有的边信息
                edges.add(new Node(i,j,dist(points,i,j)));  //size个顶点 (size-1+1)*(size-1)个边
            }
        }
        Collections.sort(edges, new Comparator<Node>() {
            public int compare(Node n1, Node n2) {
                return n1.weight - n2.weight;  //从小到大
            }
        });
        int res = 0;
        int len = 1;
        Union union = new Union(size);
        for(Node node:edges){
            if(union.connect(node.begin,node.end)){
                res+=node.weight;
                len++;
                if(len==size){
                    break;
                }
            }
        }
        return res;
    }
    //第a个点和第b个点的曼哈顿距离
    public int dist(int[][] points,int a,int b){
        int[] aa = points[a];  //当前的点
        int[] bb = points[b];  //后面的点
        return Math.abs(aa[0] - bb[0]) + Math.abs(aa[1] - bb[1]);
    }
}
//并查集去环
class Union{
    int[] parent;
    int[] ranks;
    public Union(int n){
        parent = new int[n];
        ranks = new int[n];
        for(int i=0;i<n;i++){
            parent[i] = i;  //自己指向自己
            ranks[i] = 1;    //ranks高度为1
        }
    }
    public boolean connect(int a,int b){
        int p1 = find(a);
        int p2 = find(b);
        if(p1==p2){
            return false;
        }
        if(ranks[p1]>ranks[p2]){
            parent[p2] = parent[p1];
        }else if(ranks[p1]<ranks[p2]){
            parent[p1] = parent[p2];
        }else{
            parent[p1] = parent[p2];
            ranks[p2] +=1;
        }
        return true;
    }
    public int find(int v){
        if(v != parent[v]){
            parent[v] = find(parent[v]);
        }
        return parent[v];
    }
}
//所有边的信息
class Node{
    int begin;  //第begin个顶点
    int end;   //第end个顶点
    int weight;
    public Node(int begin,int end,int weight){
        this.begin = begin;
        this.end = end;
        this.weight = weight;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

践行~渐远

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值