python应用——最小生成树实现旅行商问题

一.题目要求

    用最小生成树结合所提供的论文解决旅行商问题。

二.思路分析

Step1:用Prim算法生成最小生成树

Step2:根据最小生成树中各边的权重及各点的度,从大到小对最小生成树进行剪枝操作,使各点的度为01。这个功能在程序中使用函数jianzhi实现的。

Step3:将剪枝的结果连接成环,这个功能在程序中使用cicle函数实现。需要分为3步:

第一步:连接度为0的孤立点,使各点的度大于0,连接成一个个子图

第二步:处理当度为1的点数大于2的情况,将各子图连接为一条链

第三步:连接剩下的两个度为1的点,成为一个环

 

三.实验程序

# -*-coding:gbk-*-
from numpy import *
import Graph #Graph邻接矩阵类,使用到的功能:.out_edges提供连接节点表(连接节点,权重)///.vertex_num获得顶点数
import  PrioQueue #基于堆结构实现优先队列的类
from Graph import  Graph
from PrioQueue import  PrioQueue
##############################最小生成树算法
def Prim(graph):
    vnum = graph.vertex_num()#顶点数
    
mst = [None]*vnum    #最小生成树边表,每个元素的形式为((i,j)w),初始所有点都不属于U,为None。最小生成树原则上有n-1条边,为实现方便,加入了((0,0,),0),共有n条
    
cands = PrioQueue([(0, 0, 0)]) # 记录候选最短边,形式为(w, vi, vj),vi到vj的权重为w。元组的大小比较逐个比较各个元素,这里首先比较w
    
count = 0#记录最小生成树顶点数
    # 第一次迭代将设置 mst[0] = ((0, 0), 0),不必专门写
    
while count < vnum and not cands.is_empty():#顶点数为n或发现网络不连通
        
w, u, v = cands.dequeue() # 顶端弹出,向下筛选,取当时的最短边的(w,i,j)
        
if mst[v]:   #该顶点已加入最小生成树,边表非空
            
continue             # 邻接顶点v已在mst,跳出本次循环继续,弃掉该边
        
mst[v] = ((u, v), w) # 记录新的MST边和顶点
        
count += 1
        for vi, w in graph.out_edges(v): # 考虑v的邻接顶点vi,某行连接节点表[(节点,权重)。。。]
            
if not mst[vi]:        # 如果对已知在U中的v,相邻接的vi不在U中,则将这条边列入侯选边
                
cands.enqueue((w, v, vi))#尾端插入,向上筛选
    
return mst


##############################剪枝
def jianzhi(tree):#最小生成树tree((i,j),S)
    
tree.remove(((0, 0), 0))#删去为计算方便使用的第一个顶点到自身的边
    #排序后从大到小删去度大于2的边
    
treesort=sorted(tree,key=lambda S: S[1],reverse=True)#lambda是匿名函数,入口为S,返回S[1],将边按距离从大到小进行排序
    
print('Prim tree按边距从大到小排序treesort:',treesort)
    finddu=dict()
    for ((u, v), w) in treesort:#建立最小生成树各点度字典
        
if u not in finddu:

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值