首页 > 编程语言 >代码随想录算法训练营第59天 | 最小生成树

代码随想录算法训练营第59天 | 最小生成树

时间:2024-08-06 17:41:35浏览次数:16  
标签:__ 59 val 训练营 随想录 v1 v2 edges self

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()
    

标签:__,59,val,训练营,随想录,v1,v2,edges,self
From: https://www.cnblogs.com/P201821440041/p/18345675

相关文章

  • 代码随想录Day7
    454.四数相加Ⅱ给你四个整数数组nums1、nums2、nums3和nums4,数组长度都是n,请你计算有多少个元组(i,j,k,l)能满足:0<=i,j,k,l<nnums1[i]+nums2[j]+nums3[k]+nums4[l]==0示例1:输入:nums1=[1,2],nums2=[-2,-1],nums3=[-1,2],nums4=[0,2]输......
  • 代码随想录Day6
    454.四数相加Ⅱ给你四个整数数组nums1、nums2、nums3和nums4,数组长度都是n,请你计算有多少个元组(i,j,k,l)能满足:0<=i,j,k,l<nnums1[i]+nums2[j]+nums3[k]+nums4[l]==0示例1:输入:nums1=[1,2],nums2=[-2,-1],nums3=[-1,2],nums4=[0,2]输......
  • 「代码随想录算法训练营」第三十天 | 动态规划 part3
    46.携带研究材料(0-1背包问题)题目链接:https://kamacoder.com/problempage.php?pid=1046文章讲解:https://programmercarl.com/背包理论基础01背包-1.html视频讲解:https://www.bilibili.com/video/BV1cg411g7Y6/题目状态:看题解过思路:创建一个二维的dp数组,用来进行动态规划,其......
  • 代码随想录二刷栈与队列
    代码随想录二刷栈与队列栈模拟队列具体思路如下:程序如下:classMyQueue:def__init__(self):self.stack_in=[]self.stack_out=[]defpush(self,x:int)->None:self.stack_in.append(x)defpop(self)->int:if......
  • Studying-代码随想录训练营day59| dijkstra(堆优化版)精讲、Bellman_ford 算法精讲
    第59天,dijkstra算法的优化版本,以及Bellman_ford算法......
  • P9596 冒泡排序 2 题解
    题目链接。Statement记\(f(A)\)为序列\(A\)的冒泡排序趟数,操作:单点改,全局查\(f(A)\).\(n,m\le5\cdot10^5\),值域1e9.Solution结论:\[Ans=\max_{i\in[1..n]}\left\{\sum_{j\in[1..i]}[A_j>A_i]\right\}\]怎么观察出来啊QAQ证明:对于每个位置\(p\),观察到每趟都......
  • 代码随想录Day5
    242.有效的字母异位词给定两个字符串s和t,编写一个函数来判断t是否是s的字母异位词。注意:若s和t中每个字符出现的次数都相同,则称s和t互为字母异位词。示例1:输入:s="anagram",t="nagaram"输出:true示例2:输入:s="rat",t="car"输出:false......
  • 代码随想录算法训练营day04之字符串
    题目及链接:344.反转字符串541.反转字符串||卡码网54.替换数字151.翻转字符串里的单词卡码网55.右旋字符串28.找出字符串中第一个匹配项的下标459.重复的子字符串344.反转字符串太简单就不写了541.反转字符串||题意:给定一个字符串s和一个整数k,从字符串开头算起,每......
  • 代码随想录day20 || 235 二叉搜索树最近公共祖先,701 二叉搜索树插入,450,二叉搜索树删除
    235二叉搜索树最近公共祖先unclowestCommonAncestor(root,p,q*TreeNode)*TreeNode{ //本题相较于普通二叉树寻找最近公共祖先加了题设条件二叉搜索树,所以使用二叉搜索树特性 //如果root大于两个目标节点,那么目标都在root左子树 //如果root小于两个目标节点,那么目......
  • P3959 [NOIP2017 提高组] 宝藏
    思路:考虑状态压缩动态规划。定义\(dp_{i,j,S}\)表示点\(j\)离起点\(i\)的距离,且从点\(j\)开始打通的点集为\(S\)的最小代价(注意\(S\)不能包含\(j\))。考虑枚举\(S\)一个一个子集\(S'\),同时枚举一个\(k\),需要满足\(k\inS'\),即我们可以先打通\(j\tok\),然后......