JAVA实践最小生成树---kruskal算法

来源:互联网 发布:nginx 泛解析 编辑:程序博客网 时间:2024/05/21 07:13

前言

最小生成树的个人理解:
整条路径没有环,同时任意两点只有一条路
顶点与边数的关系是 边数 = 顶点数 - 1
路径最短

最小生成树的用途比较实际,比如如何以最短的路径走8个地方一遍,且不重复。
而Kruskal算法就可以解决此问题。

实现功能

基于Kruskal算法实现对现有的无向图生成最小树
并计算整条路径的长度输出

中文版参考

/** * 最小生成树算法--Kruskal算法: *      原理: *          将每一条边按权值从小到大排序 *          假设所有顶点尚未连接 *          然后按权值对它们进行连接 *          若已连通,那么跳过 * *          判断是否已连通:可通过深度/广度/并查集算法 *          使用并查集解决效率更高 * *  6   9 *  2   4   11 *  3   5   13 *  4   6   3 *  5   6   4 *  2   3   6 *  4   5   7 *  1   2   1 *  3   4   9 *  1   3   2 * *  按权值排序 *  1   2   1 *  1   3   2 *  4   6   3 *  5   6   4 *  2   3   6 *  4   5   7 *  3   4   9 *  2   4   11 *  3   5   13 * * 假设以上各个顶点之间尚未连接 *  1 - 2权值最小 *  判断1和2是否已连接,否,连接1-2 *  1 - 3,判断是否已连接,否,连接1-3 *  4 - 5,判断是否已连接,否,连接4-6 *  连接5-6 *  尝试连接2-3时,发现可以2->1->3,表示2与3是连通的,跳过连接2-3 *  其他同理,若能到达的两个点则跳过 * *  算法都是之前学过的并查集,排序那块可以自己写个快排排着玩- - *  我就偷懒了,直接用了java自带的(逃 */

代码实现

public class MinGenerationTree  {    public static void main(String[] args) {        Scanner in = new Scanner(System.in);        int n, m, sum = 0, count = 0;        int[] f;        Edge[] edges;        n = in.nextInt();        m = in.nextInt();        f = new int[n + 1];        edges = new Edge[m];        for (int i = 1; i <= n; i++) {            f[i] = i;        }        for (int i = 0; i < m; i++) {            edges[i] = new Edge(in.nextInt(), in.nextInt(), in.nextInt());        }        Arrays.sort(edges);        for (int i = 0; i < edges.length; i++) {            if (merge(f, edges[i].getFrom(), edges[i].getTo())) {                sum += edges[i].getWeight();                count++;            }            if (count == n - 1) {                break;            }        }        System.out.println(sum);    }    public static boolean merge(int[] f, int a, int b) {        int t1, t2;        t1 = getRoot(f, a);        t2 = getRoot(f, b);        if (t1 != t2) {            f[t2] = t1;            return true;        }        return false;    }    public static int getRoot(int[] f, int i) {        if (f[i] == i) {            return i;        } else {            f[i] = getRoot(f, f[i]);            return f[i];        }    }}class Edge implements Comparable {    private int from, to, weight;    Edge(int from, int to, int weight) {        this.from = from;        this.to = to;        this.weight = weight;    }    public void setFrom(int from) {        this.from = from;    }    public void setTo(int to) {        this.to = to;    }    public void setWeight(int weight) {        this.weight = weight;    }    public int getFrom() {        return from;    }    public int getTo() {        return to;    }    public int getWeight() {        return weight;    }    @Override    public int compareTo(Object o) {        return this.weight - ((Edge)o).weight;    }}

结果

输入   6   9   2   4   11   3   5   13   4   6   3   5   6   4   2   3   6   4   5   7   1   2   1   3   4   9   1   3   2输出19

结尾一点话

这个算法,算是其他思想的结合。
贪心、并查集。可见学习算法不会知道了就好,而是要深入了解其特点,才会清楚该算法/数据结构的特性,综合起来去解决实际问题。

END

0 0
原创粉丝点击