克鲁斯卡尔算法(并查集)

最小生成树能够保证整个拓扑图的所有路径之和最小,但不能保证任意两点之间是最短路径。

import java.util.Arrays;
import java.util.Comparator;

public class MyKruskal {
    
    
    public static final int N = 100000;// 用10000表示两个结点之间不能连接,或者也可以用Integer.MAX_VALUE

    public static void main(String[] args) {
    
    
        int[][] map = {
    
    
                {
    
    N, 12, N, N, N, 16, 14},
                {
    
    12, N, 10, N, N, 7, N},
                {
    
    N, 10, N, 3, 5, 6, N},
                {
    
    N, N, 3, N, 4, N, N},
                {
    
    N, N, 5, 4, N, 2, 8},
                {
    
    16, 7, 6, N, 2, N, 9},
                {
    
    14, N, N, N, 8, 9, N}
        };
        kruskal(map);
    }

    public static void kruskal(int[][] map) {
    
    
        int numOfVertex = map.length;// 结点的数量
        int numOfEdge = 0;// 边的数量
        for (int i = 0; i < numOfVertex; i++) {
    
    
            for (int j = i + 1; j < numOfVertex; j++) {
    
    
                if (map[i][j] != N) {
    
    
                    numOfEdge++;
                }
            }
        }
        // 根据邻接矩阵得到边集数组
        Edge[] edges = new Edge[numOfEdge];
        int index = 0;
        for (int i = 0; i < numOfVertex; i++) {
    
    
            for (int j = i + 1; j < numOfVertex; j++) {
    
    
                if (map[i][j] != N) {
    
    
                    edges[index++] = new Edge(i, j, map[i][j]);
                }
            }
        }
        // 对边集数组进行排序
        Arrays.sort(edges, new Comparator<Edge>() {
    
    
            @Override
            public int compare(Edge o1, Edge o2) {
    
    
                return o1.weight - o2.weight;
            }
        });
        
        UF uf = new UF(numOfVertex);
        for (int i = 0; i < numOfEdge; i++) {
    
    
            if (uf.union(edges[i].from, edges[i].to)) {
    
    
                System.out.println("<" + "from = " + edges[i].from + ", to = " + edges[i].to + ">的权值是:" + edges[i].weight);
            }
        }
    }
}

class Edge {
    
    
    int from;// 边的起始顶点
    int to;// 边的终止顶点
    int weight;// 边的权值

    public Edge(int from, int to, int weight) {
    
    
        this.from = from;
        this.to = to;
        this.weight = weight;
    }

    @Override
    public String toString() {
    
    
        return "Edge{" + "from=" + from + ", to=" + to + ", weight=" + weight + '}';
    }
}

class UF {
    
    
    int[] parent;
    int[] size;

    public UF(int n) {
    
    
        parent = new int[n];
        size = new int[n];
        for (int i = 0; i < n; i++) {
    
    
            parent[i] = i;
            size[i] = 1;
        }
    }

    public int find(int x) {
    
    
        while (x != parent[x]) {
    
    
            parent[x] = parent[parent[x]];
            x = parent[x];
        }
        return x;
    }

    public boolean union(int p, int q) {
    
    
        int rootP = find(p);
        int rootQ = find(q);
        if (rootP == rootQ) {
    
    
            return false;
        }
        if (size[rootP] > size[rootQ]) {
    
    
            parent[rootQ] = rootP;
            size[rootP] += size[rootQ];
        } else {
    
    
            parent[rootP] = rootQ;
            size[rootQ] += size[rootP];
        }
        return true;
    }
}

Guess you like

Origin blog.csdn.net/weixin_46497503/article/details/117431264