当前位置: 首页 > news >正文

狮山网站建设app开发网站建设哪家好

狮山网站建设,app开发网站建设哪家好,传媒网站设计公司,企业网站博客上如何营销算法核心代码实现负权环判断负权环 根据松弛次数根据最短路径上的死循环 SPFA#xff08;Shortest Path Faster Algorithm#xff09;#xff08;队列优化#xff09;算法是求单源最短路径的一种算法。它是在Bellman-ford算法的基础上加上一个队列优化#xff0c;减少了冗… 算法核心代码实现负权环判断负权环 根据松弛次数根据最短路径上的死循环 SPFAShortest Path Faster Algorithm队列优化算法是求单源最短路径的一种算法。它是在Bellman-ford算法的基础上加上一个队列优化减少了冗余的松弛操作是一种高效的最短路算法。 Bellman-Ford算法虽然可以处理负环但是时间复杂度为O(ne)e为图的边数在图为稠密图的时候是不可接受的。 Bellman-Ford算法的缺点在于当某一个迭代求解已经获得了所有的最短路径后它还是会继续执行没有执行完的迭代求解。但其实不用这样。 分析不难发现起点s到某一个点的最短路径的第一条边必定是s与s的邻接点连成的边。所以当我们在第一次松弛即第一次迭代求解时时松弛的边必定包含最短路径的第一条边。 而最短路径的第二条边必定是s的邻接点与s的邻接点的邻接点连成的边。这样以此类推。 算法核心 因此可以对算法进行优化。设置一个队列初始的时候将s放入队列中。 【1】队列出队出队元素为current松弛current与其邻接点相连的边将松弛成功的邻接点放入队列中这些点中包含其最短路径的第二个点第一个点为起点 【2】然后再次队列出队出队元素为current松弛current与其邻接点相连的边但如果已在队列中就不要重复入队了 【3】重复以上步骤 其实这个步骤和无权最短路径算法有点像。 代码实现 from queue import Queue class Edge():def __init__(self,u,v,cost):self.u uself.v vself.cost cost nodenum 5edgeList [] dis [float(inf)]*nodenum pre [-1]*nodenum know [False]*nodenum#代表已在队列之中edgeList.append(Edge(1,4,2)) edgeList.append(Edge(0,2,4)) edgeList.append(Edge(3,2,5)) edgeList.append(Edge(3,1,1)) edgeList.append(Edge(1,3,2)) edgeList.append(Edge(4,3,-3)) edgeList.append(Edge(0,1,-1)) edgeList.append(Edge(1,2,3))edgenum len(edgeList)original 0 def SPFA(original):q Queue()dis[original] 0know[original] Trueq.put(original)while(not q.empty()):current q.get()know[current] False#循环遍历current的邻接顶点for edge in edgeList:if(edge.u current):#current点的邻接边temp dis[edge.u] edge.costif(temp dis[edge.v]):#松弛操作dis[edge.v] temppre[edge.v] currentif(not know[edge.v]):q.put(edge.v)know[edge.v] Trueprint(当前出队的元素为,current)print(dis)print(pre,\n)SPFA(original) print(\n,dis) print(pre) 从运行结果可以看出程序的执行过程。2出队了两次说明它也入队了两次。从上到下观察dis数组可以发现每个点的dis最多被更新两次有的更新一次就更好好了。 负权环 当图中有负权环时队列就不会有空的情况了因为由于负权环的存在负权环上的点就可以一直被松弛一直能被松弛就代表着队列会不断反复让负权环上的点入队出队程序就会死循环。 修改边的权重为 edgeList.append(Edge(0,1,-1)) edgeList.append(Edge(1,2,3)) edgeList.append(Edge(3,1,1)) edgeList.append(Edge(1,3,2)) edgeList.append(Edge(1,4,2)) edgeList.append(Edge(0,2,4)) #edgeList.append(Edge(3,2,5)) edgeList.append(Edge(2,3,-5)) edgeList.append(Edge(4,3,-3)) 如图所示形成了123的负权环。 此时运行结果会无限输出不停有元素出队入队所以程序陷入了死循环。 判断负权环 根据松弛次数 n代表节点个数。 根据松弛次数是否大于等于n来判断负权环是从网上其他博客说的根据出队次数是否大于等于n来判断想到的。因为判断出队次数是判断更新次数的上界。 用一个n大小的数组来代表每个点的松弛次数。因为SPFA算法里的松弛和Bellman-ford算法里的松弛一样。Bellman-ford算法里对同一个点的松弛次数在极端情况下可以想象把这些松弛次数分配到每一次迭代求解中去而迭代求解一共只有n-1次。所以一旦某个点的松弛次数等于了n那么就说明有负环。 所以在每次进行松弛后遍历判断每个点的松弛次数如果有一个等于n再执行下去就会大于n就说明有负环。 #用松弛次数来判断负权环 from queue import Queue class Edge():def __init__(self,u,v,cost):self.u uself.v vself.cost cost nodenum 5edgeList [] dis [float(inf)]*nodenum pre [-1]*nodenum know [False]*nodenum#代表已在队列之中update [0]*nodenum#代表每个点被更新的次数edgeList.append(Edge(0,1,-1)) edgeList.append(Edge(1,2,3)) edgeList.append(Edge(3,1,1)) edgeList.append(Edge(1,3,2)) edgeList.append(Edge(1,4,2)) edgeList.append(Edge(0,2,4)) #edgeList.append(Edge(3,2,5)) edgeList.append(Edge(2,3,-5)) edgeList.append(Edge(4,3,-3))edgenum len(edgeList)original 0 def SPFA(original):q Queue()dis[original] 0know[original] Trueq.put(original)while(not q.empty()):current q.get()know[current] Falseflag False#负环判断标记#循环遍历current的邻接顶点for edge in edgeList:if(edge.u current):#current点的邻接边temp dis[edge.u] edge.costif(temp dis[edge.v]):#松弛操作dis[edge.v] temppre[edge.v] currentupdate[edge.v] 1for i in update:if(inodenum):flag Trueprint(最后一次出队的是,current)breakif(flag True):breakif(not know[edge.v]):q.put(edge.v)know[edge.v] Trueif(flag True):breakprint(当前出队的元素为,current)print(dis)print(pre,\n)SPFA(original) print(dis,dis) print(pre,pre) print(update,update) 运行结果并没有全部截图下来因为中间执行了很多次不该有的出队入队操作每次出队都输出东西这里只截了最后结果。可以看到update数组中有一个等于了5所以程序就判断有了负权环。 而且读者可以通过所有的输出结果统计每个点出队次数会发现这些点里面出队次数最大也就为4我用画正字来记的数。意思就是如果程序通过出队次数来判断的话那么程序还得多执行几次不该有的出队入队操作。这也证实了判断出队次数是判断更新次数的上界。 但通过所有输出结果还是觉得程序判断出负权环判断得太迟了中间执行了很多次不该有的出队入队操作有没有一种更快的方法可以及早判断出负权环呢。答案是有如下。 根据最短路径上的死循环 寻找最短路径的方法是通过pre数组 比如代码实现章节的程序运行后pre数组为[-1, 0, 1, 4, 1]要寻找从起点0到3的最短路径步骤如下 【1】记录下3路径为3 【2】记录下pre[3]4路径为43 【3】记录下pre[4]1路径为143 【4】记录下pre[1]0路径为0143 【4】记录下pre[0]-1遇到-1到达终点返回路径0143 从起点到某点的最短路径路径上的点必定都是不重复的。但当有负权环时这句话就不成立了。 比如负权环章节的程序运行后pre数组为[-1, 3, 1, 2, 1]寻找从起点0到3的最短路径会发现上述步骤会一种进行下去因为到达不了终点死循环了虽然这里程序是用的递归。 #此程序用pre数组的死循环来判断是否有负环 from queue import Queue class Edge():def __init__(self,u,v,cost):self.u uself.v vself.cost cost nodenum 5edgeList [] dis [float(inf)]*nodenum pre [-1]*nodenum know [False]*nodenum#代表已在队列之中edgeList.append(Edge(0,1,-1)) edgeList.append(Edge(1,2,3)) edgeList.append(Edge(3,1,1)) edgeList.append(Edge(1,3,2)) edgeList.append(Edge(1,4,2)) edgeList.append(Edge(0,2,4)) #edgeList.append(Edge(3,2,5)) edgeList.append(Edge(2,3,-5)) edgeList.append(Edge(4,3,-3))edgenum len(edgeList)original 0def if_circle(pre):#判断是否有负权环返回真假如有负权环并返回环prev -1#设置环的起点circle []#记录负权环def get(i):circle.append(i)if(i -1):#到达了正常的终点判断无负权环return Falseif(i prev):#到达了不该达到的终点判断有负权环return Truereturn get(pre[i])for i in pre:if(i -1):#超出索引限制了continueprev iif(get(pre[i])):#传入参数直接是i的上一个顶点直接传入i会出错return (True,circle)circle.clear()return (False,)def SPFA(original):q Queue()dis[original] 0know[original] Trueq.put(original)while(not q.empty()):current q.get()know[current] Falseflag False#循环遍历current的邻接顶点for edge in edgeList:if(edge.u current):#current点的邻接边temp dis[edge.u] edge.costif(temp dis[edge.v]):#松弛操作dis[edge.v] temppre[edge.v] currentif(if_circle(pre)[0]):print(有负环为,if_circle(pre)[1])print(dis)print(pre)flag Truebreakif(not know[edge.v]):q.put(edge.v)know[edge.v] Trueif(flag True):breakprint(当前出队的元素为,current)print(dis)print(pre,\n)SPFA(original) print(\n,dis) print(pre) 通过这种方式程序可以很快地判断出来负权环程序只出队了4次就判断出来了。且得到了负权环的组成的点[2, 1, 3]。
http://www.hkea.cn/news/14492541/

相关文章:

  • 十大搜索引擎网站郑州便宜网站建设费用
  • 中国建设工程安全管理协会网站免费文档模板素材网站
  • 创口贴网站模板网站建设捌金手指花总十三
  • 网站备案 网站建设方案书提高网页加载速度的方式
  • 简单响应式网站设计代码如何进行营销型企业网站的优化
  • 深圳网站建设最好网页制作公司南昌
  • 建设创意网站seo推广培训班
  • cms建站系统免费wordpress 去除底部
  • 建立个人网站服务器襄阳网站seo
  • 一个网站大概多少页面网络服务提供者收集和使用个人信息应当符合的条件有
  • 梅州网站建设公司视频教学互动网站建设
  • 桥东网站建设建设银行网站背景
  • 怎么做网站自动响应外包公司与劳务派遣区别
  • 受欢迎的网站建设教程房地网站制作
  • 网站如何做微信支付宝支付宝支付宝goule wordpress
  • 警告欺骗网站模板nodejs做后端的网站
  • 网站推广方式主要通过怎么将自己的视频推广出去
  • 网站后台传不上图片腾讯云网站搭建流程
  • 简单建网站公司注册代理机构
  • 建网站需要注意的问题贵阳app开发公司排名
  • 宁波网站备案幕布拍照网站建设业务拓展思路
  • 织梦网站专题页面如何做WordPress只能ssl
  • 腾讯云个人网站备案wordpress 时间设置
  • 天津市市建设与管理局网站传媒公司制作网站
  • 网站建设费如何做账开发一个app需要什么流程
  • 郑州企业做网站h汉狮商城系统网站建设
  • 达人室内设计网注册seo站内优化和站外优化
  • 网站建设运维方案网站建设后端
  • 网站备案代码生成哈尔滨网站建设公司那家好
  • 景区官方网站建设方案咸阳网站制作