Java算法:最小生成树

航海家们在太平洋上发现了几座新岛屿,其中最大的一个岛已经连接到Internet,但是其它岛和主岛之间没有电缆连接,所以无法入网。我们的目的是让所有岛上的居民都能上网,即每个岛和主岛之间都有直接或间接的电缆连接。输入每两个岛屿之间的连接成本,要求给出最节省成本的方案。
在这里插入图片描述

先输入点的数量n,边的数量m,然后输入m行数据,每行数据包括起点u,终点v,成本weight,最后输出最优方案所选的边;

样例输入:

7 11
0 1 7
0 3 5
1 2 8
1 3 9
1 4 7
2 4 5
3 4 15
3 5 6
4 5 8
4 6 9
5 6 11
样例输出:

0 3 5
2 4 5
3 5 6
0 1 7
1 4 7
4 6 9

Kruskal算法
根据权值对边排序,每次选择权值最小的边,选择过程利用并查集判断一下是否为同一个连通分量,即防止形成环

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

public class Main {

	static class Edge {

		int u;
		int v;
		int weight;

		public Edge(int u, int v, int weight) {
			this.u = u;
			this.v = v;
			this.weight = weight;
		}
	}

	// 查找根节点
	public static int find(int[] p, int x) {
		if (p[x] == x)
			return x;
		else
			return p[x] = find(p, p[x]);
	}

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		Edge[] edges = new Edge[m];

		for (int i = 0; i < m; i++) {
			int u = sc.nextInt();
			int v = sc.nextInt();
			int weight = sc.nextInt();
			edges[i] = new Edge(u, v, weight);
		}
		Arrays.sort(edges, new Comparator<Edge>() {

			@Override
			public int compare(Edge o1, Edge o2) {
				return o1.weight - o2.weight;
			}
		});
		int[] p = new int[n];
		for (int i = 0; i < n; i++) {
			p[i] = i;
		}
		for (int i = 0; i < m; i++) {
			int x = find(p, edges[i].u);
			int y = find(p, edges[i].v);
			// 判断是否为一个连通分量,防止形成环
			if (x == y)
				continue;
			else {
				// 合并连通分量
				p[x] = y;
				System.out.println(edges[i].u + " " + edges[i].v + " " + edges[i].weight);
			}
		}
	}
}

Prim算法求最小生成树总权值
构造点的集合,dis[ i ]存点i到其余点的最小权值,每次都会更新,假设从0点开始,就把点0加入集合,选0到其余点的最小权值,循环n次选出n个点,其中把最小生成树权值都加起来
先输入点的数量n,边的数量m,然后输入m行数据,每行数据包括起点u,终点v,成本weight,最后输出最小生成树的总权值。

样例输入:

7 11
0 1 7
0 3 5
1 2 8
1 3 9
1 4 7
2 4 5
3 4 15
3 5 6
4 5 8
4 6 9
5 6 11
样例输出:

39

import java.util.Arrays;
import java.util.Scanner;

public class Main {

	static class Edge {
		int u;
		int v;
		int weight;

		public Edge(int u, int v, int weight) {
			this.u = u;
			this.v = v;
			this.weight = weight;
		}

	}

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int[][] edges = new int[n][n];
		for (int i = 0; i < m; i++) {
			int u = sc.nextInt();
			int v = sc.nextInt();
			int weight = sc.nextInt();
			edges[u][v] = weight;
			edges[v][u] = weight;
		}
		// dis[i]表示存放结点i到已访问结点的最小权值
		int[] dis = new int[n];
		int[] vis = new int[n];// 标记数组
		Arrays.fill(dis, Integer.MAX_VALUE);
		dis[0] = 0;
		int res = 0;
		for (int i = 0; i < n; i++) {
			int x = -1;
			int min = Integer.MAX_VALUE;
			for (int j = 0; j < n; j++) {
				if (vis[j] == 0 && dis[j] < min) {
					x = j;
					min = dis[j];
				}
			}
			res += min;
			vis[x] = 1;
			// 更新选中点到其它点的dis值
			for (int k = 0; k < n; k++) {
				if (vis[k] == 0 && edges[x][k] > 0) {
					if (dis[k] > edges[x][k]) {
						dis[k] = edges[x][k];
					}
				}
			}
		}
		System.out.println(res);
	}
}

参考博客【java】最小生成树

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值