代码随想录算法训练营第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算法精讲

  • 核心:选择距离最近的点

  • 步骤

    1. 选择距离生成树最近节点
    2. 最近节点加入生成树
    3. 更新非生成树节点到生成树的距离(即更新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()
    
posted @ 2024-08-06 17:31  哆啦**  阅读(1)  评论(0编辑  收藏  举报