最小生成树算法简介-prim 和 kruskal 算法
1220
2022.12.03
发布于 未知归属地

prim算法描述

1. 初始化集合s(已加入的点的集合) = {}, dist={无穷大}:含义为到集合s的距离
2. 循环n次(每次在集合外找一个距离最小的点加入集合)
      在dist集合外找一个距离最小的点t, 加入集合s
      更新dist, 用t作为中转点去更新其他点到集合的距离


总结: 和dijstra算法的区别在于一个是更新到起点的距离, 一个是更新到集合v的距离

Kruskal算法描述

1. 将所有边按权重从小到大排序 (o(mlogm))
2. 枚举每条边a,b, 权重为c. (o(m))
   if a和b不联通, 将边加入集合中 

主要是并查集实现

prim算法实现

//g: 邻接矩阵
//return: (最小代价, 是否存在最小代价(true:存在))
func prim(g [][]int) (int, bool) {
	n := len(g)
	dist := make([]int, n)
	for i := 0; i < n; i++ {
		dist[i] = 0x3f3f3f3f
	}

	visit := make([]bool, n)
	res := 0
	for i := 0; i < n; i++ {
		t := -1
		for j := 0 ;j < n; j++ {
			if !visit[j] && (t == -1 || dist[j] < dist[t]) {
				t = j
			}
		}
		visit[t] = true
		if i == 0 {
			dist[t] = 0
		}
		if dist[t] ==  0x3f3f3f3f {
			return 0, false
		}
		res += dist[t]
		for j := 0; j < n;j++ {
			if !visit[j] && dist[j] > g[t][j] {
				dist[j] = g[t][j]
			}
		}
	}
	return res, true
}

Kruskal算法实现

type Edge struct {
	st int
	ed int
	w int
}
var parent []int

func findpa(a int) int {
	if a != parent[a] {
		parent[a] = findpa(parent[a])
	}
	return parent[a]
}

func kruskal(edges []*Edge, n int) (int, bool){
	sort.Slice(edges, func(i, j int) bool {
		return edges[i].w < edges[j].w
	})

	cnt := 0
	res := 0
	parent = make([]int, n)
	for i := 0; i < n; i++ {
		parent[i] = i
	}
	for i := 0; i < len(edges);i++{
		pa := findpa(edges[i].st)
		pb := findpa(edges[i].ed)
		if pa != pb {
			cnt++
			res += edges[i].w
			parent[pa] = pb
		}
	}
	if cnt != n-1 {
		return 0, false
	}
	return res, true
}

应用场景

  • 覆盖所有顶点的最小代价,比如要在n个城市铺设光缆,使得n个城市任意两个都可以通信,目标是如何铺设路线, 才可以使得总费用最低
评论 (0)