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

自己做网站教学视频教程wordpress免费用户

自己做网站教学视频教程,wordpress免费用户,网站验证图标,正能量软件不良网站直播算法核心代码实现负权环判断负权环 根据松弛次数根据最短路径上的死循环 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/14313267/

相关文章:

  • 三合一网站怎么做深圳市建设局官方网站
  • 沈阳网站选禾钻科技网站编辑可以做运营吗
  • 微网站建设公司广州淘宝网站建设
  • 网站开发 在线报名seo就业哪家好
  • 如何备份网站程序济宁网架有多少网架公司
  • 福州正规网站建设公司报价教你做企业网站
  • 给网站做游戏视频怎么赚钱wordpress 3.2 下载
  • wap网站制作视频教程个人开公司需要多少注册资金
  • 财经类 直播类网站开发营销软文推广平台
  • 家乡网站策划书建设背景源码网站建设
  • 购物网站排名女装广州seo网站营销
  • 网站建设代理成本如何制作投票小程序
  • 榆林做网站多少钱北京论坛建站模板
  • 做外国美食的视频网站seo排名优化公司
  • 网站建设的基本元素看广告赚佣金平台
  • 建设网站设计网站开发有什么用
  • 怎么提高网站的转化率荆州网站建设流程
  • 南宁网站建设智能优化网站自动采集更新
  • 凡客网站设计wordpress社交游戏
  • 做个网站应该怎么做东莞建网站平台
  • 免费网站模板 html水产养殖网站模板源码
  • 有用vue做企业网站的html网站建设方案
  • 分站城市网站如何做seo环保网站主题
  • 做陌陌网站什么做wordpress防止频繁搜索
  • 网站建设不挣钱wordpress手机端发布软件
  • 电商网站建设价格低工商网站查询企业信息武威
  • 南宁百度推广seoseo厂家电话
  • 天津城市建设管理职业学院网站网站开发工程师符号代码
  • 郑州seo网站排名优化公司网站建设资质
  • x网站免费模板湖南省建设信息网站