代码随想录算法训练营第59天 | 最小生成树
53.寻宝
https://kamacoder.com/problempage.php?pid=1053
prim算法精讲
https://www.programmercarl.com/kamacoder/0053.寻宝-prim.html
kruskal算法精讲
https://www.programmercarl.com/kamacoder/0053.寻宝-Kruskal.html
题目描述
在世界的某个区域,有一些分散的神秘岛屿,每个岛屿上都有一种珍稀的资源或者宝藏。国王打算在这些岛屿上建公路,方便运输。
不同岛屿之间,路途距离不同,国王希望你可以规划建公路的方案,如何可以以最短的总公路距离将 所有岛屿联通起来(注意:这是一个无向图)。
给定一张地图,其中包括了所有的岛屿,以及它们之间的距离。以最小化公路建设长度,确保可以链接到所有岛屿。
- 题目解析:在点中建立连通的最小图
prim算法精讲
-
核心:选择距离最近的点
-
步骤
- 选择距离生成树最近节点
- 最近节点加入生成树
- 更新非生成树节点到生成树的距离(即更新minDist数组)
-
距离表示形式(grid)初始化为[10000 (v+1)*(v+1)]
点击查看代码
def main(): v,e = map(int,input().split()) edges = [] grid = [[10000]*(v+1) for _ in range(v+1)] for i in range(1,v+1): grid[i][i] = 0 for _ in range(e): v1,v2,val = map(int,input().split()) grid[v1][v2] = val grid[v2][v1] = val mindist = [10001]*(v+1) ##最小距离依据 istree = [False]*(v+1) ##表示生成树 mindist[1] = 0 res = 0 parent = [-1]*(v+1) for i in range(1,v+1): curr = -1 minval = 10001 for j in range(1,v+1): if not istree[j] and mindist[j]<minval: minval = mindist[j] curr = j if curr == -1: break istree[curr] = True res+=minval for j in range(1,v+1): if not istree[j] and grid[curr][j]<mindist[j]: mindist[j] = grid[curr][j] parent[j] = curr print("distance"+str(res)) for i in range(1,v+1): print(str(i)+"->"+str(parent[i])) if __name__ == '__main__': main()
kruskal算法精讲
-
核心:选择距离最近的边
-
步骤:
- 将每条边按照val排序;
- 如果两个边的节点不在生成树内,加入生成树
- 如何判断边在不在生成树内:
-判断交集 rank将树的高度降低
点击查看代码
class unionfold: def __init__(self,size): self.root = [ i for i in range(size)] self.rank = [1]*size def find(self,x): if self.root[x]!=x: self.root[x] = self.find(self.root[x]) return self.root[x] def union(self,x,y): x = self.find(x) y = self.find(y) if x!=y: if self.rank[x]>self.rank[y]: self.root[y] = x elif self.rank[y]>self.rank[x]: self.root[x] = y else: self.root[y] = x self.rank[x]+=1 def issame(self,x,y): x = self.find(x) y = self.find(y) return x==y class Edges: def __init__(self,v1,v2,val): self.val = val self.v1 = v1 self.v2 = v2 def main(): v,e = map(int,input().split()) edges = [] uf = unionfold(v+1) for _ in range(e): v1,v2,val = map(int,input().split()) edges.append([val,v1,v2]) edges.sort() mst_weight = 0 mst_edges = 0 # path = [] res = [] for weight,v1,v2 in edges: if not uf.issame(v1,v2): uf.union(v1,v2) mst_weight += weight mst_edges +=1 # path.append([v1,v2]) res.append(Edges(v1,v2,val)) if mst_edges==v-1: break print(uf.rank) if mst_edges ==v-1: for ed in res: print(str(ed.v1)+"->"+str(ed.v2)+":"+str(ed.val)) else: print("-1") if __name__ == '__main__': main()