# -*- encoding: utf-8 -*- from head import * from NODE import * from EDGE import * N = Node() E = Edge() class Solve: def __init__(self): self.ans = [] # 记录答案 self.mutians = [] # 若有多个最短路,则保存在mutians中 self.way_sum = 0 # 记录遍历的路径数目 self.minn = float("inf")#初始化最小值为正无穷 self.start = 0 # 起始点 self.end = 0 # 终点 self.mark = [] # 记录该点是否已经经过 self.user_cur = 0 # 记录用户所在点 self.cura = -1 # 记录用户选择的第一个点 self.curb = -1 # 记录用户选择的第二个点 self.con = 0 # 记录必经的节点数目 def Edge_mark_clear(self): for edge in d.Edges: edge[4] = 0 G.draw() def Solve_display(self): for w in frame_right.winfo_children(): w.destroy() # 清除右侧组件 self.Edge_mark_clear() cura = "无" cur1 = -1 curb = "无" cur2 = -1 lab = tk.Label(frame_right, text="自动判断相关", bg=RED, fg=BLACK, font=('微软雅黑', 20)) lab.place(relx=0.18, rely=0.02, width=200, height=30) for i in d.Nodes: if i[2] == 1: cura = str(i[1]) cur1 = i[0] if i[2] == 2: curb = str(i[1]) cur2 = i[0] y0 = 0.1 B = tk.Button(frame_right, text="查询该图是否联通", command=lambda: self.check()) B.place(relx=0.1, rely=0.0 + y0, width=150, height=30) B = tk.Button(frame_right, text="自动求解最优路径-遍历", command=lambda: self.dfs_panel()) B.place(relx=0.1, rely=0.1 + y0, width=200, height=30) B = tk.Button(frame_right, text="自动求解最优路径-贪心", command=lambda: self.greedy_panel()) B.place(relx=0.1, rely=0.15 + y0, width=200, height=30) # B.place(relx=0.1, rely=0.0 + y0, width=150, height=30) B = tk.Button(frame_right, text="自动求解最优路径(包含非必经点)", command=lambda: self.dfs_panel_condition()) B.place(relx=0.1, rely=0.2 + y0, width=200, height=30) # 当前两个节点信息 y0 = 0.4 laba1 = tk.Label(frame_right, text="当前节点1:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) laba2 = tk.Label(frame_right, text=f"{cura}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8)) laba1.place(relx=0.05, rely=0.02 + y0, width=80, height=30) laba2.place(relx=0.35, rely=0.02 + y0, width=50, height=30) labb1 = tk.Label(frame_right, text="当前节点2:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) labb2 = tk.Label(frame_right, text=f"{curb}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8)) labb1.place(relx=0.52, rely=0.02 + y0, width=80, height=30) labb2.place(relx=0.82, rely=0.02 + y0, width=50, height=30) B = tk.Button(frame_right, text="查询两节点是否联通", command=lambda: self.run_graph_check()) B.place(relx=0.1, rely=0.1 + y0, width=250, height=30) B = tk.Button(frame_right, text="查询两节点之间最优路径(时间)", command=lambda: self.auto_lowest_time()) B.place(relx=0.1, rely=0.15 + y0, width=250, height=30) B = tk.Button(frame_right, text="查询两节点之间最优路径(距离)", command=lambda: self.auto_lowest_cost()) B.place(relx=0.1, rely=0.2 + y0, width=250, height=30) B = tk.Button(frame_right, text="查询两节点之间最优路径(含必经节点)", command=lambda: self.auto_lowest_cost_condition()) B.place(relx=0.1, rely=0.25 + y0, width=250, height=30) def run_graph_check(self): a = -1 b = -1 # 根据已有数据获得a,b点的编号 for node in d.Nodes: if node[2] == 1: a = node[0] if node[2] == 2: b = node[0] if a == -1 or b == -1: tk.messagebox.askokcancel(title='错误', message='未选择节点') return self.graph_check(a, b) def graph_check(self, a, b): # 检查A点B点是否互通 find = []# 使用并查集来检测a,b点是否互通 for i in range(len(d.Nodes)):# 初始化并查集 find.append(i)#使得find[i]=i for edge in d.Edges:#根据已有的边来更新并查集 if (edge[8] == 1 and edge[3] == 0): continue x = edge[1] y = edge[2] while not x == find[x]: x = find[x] while not y == find[y]: y = find[y] if x < y: find[y] = x else: find[x] = y x = a y = b while not x == find[x]:#查询a点所在集合 x = find[x] while not y == find[y]:#查询b点所在集合 y = find[y] if find[x] == find[y]:# 输出检查结果 tk.messagebox.askokcancel(title='结果', message='节点 ' + str(a + 1) + '与节点 ' + str(b + 1) + '互通') else: tk.messagebox.askokcancel(title='结果', message='节点 ' + str(a + 1) + '与节点 ' + str(b + 1) + '不互通') def node_mark1(self, name): if name >= len(d.Nodes): N.node_404(name) return for node in d.Nodes: if node[0] == name: node[2] = 1 elif node[2] == 1: node[2] = 0 G.draw() self.Solve_display() def node_mark2(self, name): if name >= len(d.Nodes): N.node_404(name) return for node in d.Nodes: if node[0] == name: node[2] = 2 elif node[2] == 2: node[2] = 0 G.draw() self.Solve_display() def auto_lowest_time(self): # 标记遍历路径 for w in frame_right.winfo_children(): w.destroy() # 清除右侧组件 a = -1 b = -1 for node in d.Nodes: if node[2] == 1: a = node[0] if node[2] == 2: b = node[0] if a == -1 or b == -1: tk.messagebox.askokcancel(title='错误', message='未选择节点') return self.cura = a self.curb = b y0 = 0.1 self.lowest_time_dfs() # print(self.ans) laba1 = tk.Label(frame_right, text="起点:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) laba2 = tk.Label(frame_right, text=f"{d.Nodes[self.cura][1]}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8)) laba1.place(relx=0.05, rely=0.02 + y0, width=80, height=30) laba2.place(relx=0.35, rely=0.02 + y0, width=50, height=30) labb1 = tk.Label(frame_right, text="终点:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) labb2 = tk.Label(frame_right, text=f"{d.Nodes[self.curb][1]}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8)) labb1.place(relx=0.52, rely=0.02 + y0, width=80, height=30) labb2.place(relx=0.82, rely=0.02 + y0, width=50, height=30) y0 += 0.1 lab1 = tk.Label(frame_right, text="遍历路径数目:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f"{self.way_sum}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.05 + y0, width=100, height=30) lab2.place(relx=0.5, rely=0.05 + y0, width=100, height=30) lab1 = tk.Label(frame_right, text="求解花费时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f'{self.end - self.start:.4f} s', bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.10 + y0, width=100, height=30) lab2.place(relx=0.5, rely=0.10 + y0, width=100, height=30) lab = tk.Label(frame_right, text="自动求解时间最短路径", bg=RED, fg=BLACK, font=('微软雅黑', 20)) lab.place(rely=0.02, width=300, height=30) B = tk.Button(frame_right, text="返回", command=lambda: self.Solve_display()) B.place(relx=0.1, rely=y0, width=50, height=30) lab1 = tk.Label(frame_right, text="时间最短路径:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) f = 0 way = '' for a in self.ans: if f == 0: f = 1 else: way += "->" way += d.Nodes[a][1] # way += d.Nodes[0][1] # print(ans, "444", way) # print (ans) lab2 = tk.Label(frame_right, text=f"{way}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200, justify='left') tim = 0 cost = 0 for i in range(len(self.ans) - 1): tim += d.Edges[G.node_edge(self.ans[i], self.ans[i + 1])][7] cost += d.Edges[G.node_edge(self.ans[i], self.ans[i + 1])][6] lab1.place(relx=0.1, rely=0.2 + y0, width=100, height=30) lab2.place(relx=0.1, rely=0.25 + y0, width=200, height=100) lab1 = tk.Label(frame_right, text="该路径时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f"{tim} min", bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.5 + y0, width=100, height=30) lab2.place(relx=0.5, rely=0.5 + y0, width=100, height=30) lab1 = tk.Label(frame_right, text="该路径距离:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f'{cost} km', bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.55 + y0, width=100, height=30) lab2.place(relx=0.5, rely=0.55 + y0, width=100, height=30) def auto_lowest_cost_condition(self): # 标记遍历路径(必经) for w in frame_right.winfo_children(): w.destroy() # 清除右侧组件 a = -1 b = -1 for node in d.Nodes: if node[2] == 1: a = node[0] if node[2] == 2: b = node[0] if a == -1 or b == -1: tk.messagebox.askokcancel(title='错误', message='未选择节点') return self.cura = a self.curb = b y0 = 0.1 self.start = time.time() self.lowest_cost_dfs_condition() self.end = time.time() # print(self.ans) laba1 = tk.Label(frame_right, text="起点:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) laba2 = tk.Label(frame_right, text=f"{d.Nodes[self.cura][1]}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8)) laba1.place(relx=0.05, rely=0.02 + y0, width=80, height=30) laba2.place(relx=0.35, rely=0.02 + y0, width=50, height=30) labb1 = tk.Label(frame_right, text="终点:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) labb2 = tk.Label(frame_right, text=f"{d.Nodes[self.curb][1]}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8)) labb1.place(relx=0.52, rely=0.02 + y0, width=80, height=30) labb2.place(relx=0.82, rely=0.02 + y0, width=50, height=30) y0 += 0.1 lab1 = tk.Label(frame_right, text="遍历路径数目:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f"{self.way_sum}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.05 + y0, width=100, height=30) lab2.place(relx=0.5, rely=0.05 + y0, width=100, height=30) lab1 = tk.Label(frame_right, text="求解花费时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f'{self.end - self.start:.4f} s', bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.10 + y0, width=100, height=30) lab2.place(relx=0.5, rely=0.10 + y0, width=100, height=30) lab = tk.Label(frame_right, text="求解最短路径(含必经点)", bg=RED, fg=BLACK, font=('微软雅黑', 18)) lab.place(rely=0.02, width=300, height=30) B = tk.Button(frame_right, text="返回", command=lambda: self.Solve_display()) B.place(relx=0.1, rely=y0, width=50, height=30) lab1 = tk.Label(frame_right, text="距离最短路径:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) if not self.check_condition(self.ans): way = '未找到合法路径' else: f = 0 way = '' for a in self.ans: if f == 0: f = 1 else: way += "->" way += d.Nodes[a][1] lab2 = tk.Label(frame_right, text=f"{way}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200, justify='left') tim = 0 cost = 0 for i in range(len(self.ans) - 1): tim += d.Edges[G.node_edge(self.ans[i], self.ans[i + 1])][7] cost += d.Edges[G.node_edge(self.ans[i], self.ans[i + 1])][6] lab1.place(relx=0.1, rely=0.2 + y0, width=100, height=30) lab2.place(relx=0.1, rely=0.25 + y0, width=200, height=100) lab1 = tk.Label(frame_right, text="该路径时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f"{tim} min", bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.55 + y0, width=100, height=30) lab2.place(relx=0.5, rely=0.55 + y0, width=100, height=30) lab1 = tk.Label(frame_right, text="该路径距离:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f'{cost} km', bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.5 + y0, width=100, height=30) lab2.place(relx=0.5, rely=0.5 + y0, width=100, height=30) def auto_lowest_cost(self): # 标记遍历路径 for w in frame_right.winfo_children(): w.destroy() # 清除右侧组件 a = -1 b = -1 for node in d.Nodes: if node[2] == 1: a = node[0] if node[2] == 2: b = node[0] if a == -1 or b == -1: tk.messagebox.askokcancel(title='错误', message='未选择节点') return self.cura = a self.curb = b y0 = 0.1 self.start = time.time() self.lowest_cost_dfs() self.end = time.time() # print(self.ans) laba1 = tk.Label(frame_right, text="起点:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) laba2 = tk.Label(frame_right, text=f"{d.Nodes[self.cura][1]}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8)) laba1.place(relx=0.05, rely=0.02 + y0, width=80, height=30) laba2.place(relx=0.35, rely=0.02 + y0, width=50, height=30) labb1 = tk.Label(frame_right, text="终点:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) labb2 = tk.Label(frame_right, text=f"{d.Nodes[self.curb][1]}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8)) labb1.place(relx=0.52, rely=0.02 + y0, width=80, height=30) labb2.place(relx=0.82, rely=0.02 + y0, width=50, height=30) y0 += 0.1 lab1 = tk.Label(frame_right, text="遍历路径数目:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f"{self.way_sum}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.05 + y0, width=100, height=30) lab2.place(relx=0.5, rely=0.05 + y0, width=100, height=30) lab1 = tk.Label(frame_right, text="求解花费时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f'{self.end - self.start:.4f} s', bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.10 + y0, width=100, height=30) lab2.place(relx=0.5, rely=0.10 + y0, width=100, height=30) lab = tk.Label(frame_right, text="自动求解距离最短路径", bg=RED, fg=BLACK, font=('微软雅黑', 20)) lab.place(rely=0.02, width=300, height=30) B = tk.Button(frame_right, text="返回", command=lambda: self.Solve_display()) B.place(relx=0.1, rely=y0, width=50, height=30) lab1 = tk.Label(frame_right, text="距离最短路径:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) f = 0 way = '' for a in self.ans: if f == 0: f = 1 else: way += "->" way += d.Nodes[a][1] # way += d.Nodes[0][1] # print(ans, "444", way) # print (ans) lab2 = tk.Label(frame_right, text=f"{way}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200, justify='left') tim = 0 cost = 0 for i in range(len(self.ans) - 1): tim += d.Edges[G.node_edge(self.ans[i], self.ans[i + 1])][7] cost += d.Edges[G.node_edge(self.ans[i], self.ans[i + 1])][6] lab1.place(relx=0.1, rely=0.2 + y0, width=100, height=30) lab2.place(relx=0.1, rely=0.25 + y0, width=200, height=100) lab1 = tk.Label(frame_right, text="该路径时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f"{tim} min", bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.55 + y0, width=100, height=30) lab2.place(relx=0.5, rely=0.55 + y0, width=100, height=30) lab1 = tk.Label(frame_right, text="该路径距离:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f'{cost} km', bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.5 + y0, width=100, height=30) lab2.place(relx=0.5, rely=0.5 + y0, width=100, height=30) def dfs_panel_condition(self): # 标记遍历路径(区分必经/非必经) for w in frame_right.winfo_children(): w.destroy() # 清除右侧组件 y0 = 0.1 self.start = time.time() self.node_dfs_condition() self.end = time.time() lab1 = tk.Label(frame_right, text="遍历路径数目:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f"{self.way_sum}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.05 + y0, width=100, height=30) lab2.place(relx=0.5, rely=0.05 + y0, width=100, height=30) lab1 = tk.Label(frame_right, text="求解花费时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f'{self.end - self.start:.4f} s', bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.10 + y0, width=100, height=30) lab2.place(relx=0.5, rely=0.10 + y0, width=100, height=30) lab = tk.Label(frame_right, text="求解路径(区分必经点)", bg=RED, fg=BLACK, font=('微软雅黑', 20)) lab.place(rely=0.02, width=300, height=30) B = tk.Button(frame_right, text="返回", command=lambda: self.Solve_display()) B.place(relx=0.1, rely=y0, width=50, height=30) lab1 = tk.Label(frame_right, text="最短路径:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) # 根据遍历结果输出最短路径 way = "" for a in self.ans: way += d.Nodes[a][1] way += "->" way += d.Nodes[0][1] if not self.check_condition(self.ans): way = "未找到联通路径" lab2 = tk.Label(frame_right, text=f"{way}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200, justify='left') lab1.place(relx=0.1, rely=0.2 + y0, width=80, height=30) lab2.place(relx=0.1, rely=0.25 + y0, width=200, height=100) more = 0 way = '' for moreans in self.mutians: more += 1 if more > 1: way += '\n' way += str(more) + ': ' for a in moreans: way += d.Nodes[a][1] way += "->" way += d.Nodes[0][1] if more: lab1 = tk.Label(frame_right, text="其他最短路径:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = scrolledtext.ScrolledText(frame_right, width=50, height=5, bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab2.insert('end', way) lab2.configure(state=DISABLED) lab1.place(relx=0.1, rely=0.2 + y0 + 0.2, width=120, height=30) lab2.place(relx=0.1, rely=0.25 + y0 + 0.2, width=240, height=200) def dfs_panel(self): # dfs面板显示 for w in frame_right.winfo_children(): w.destroy()# 清除右侧组件 y0 = 0.1 self.start = time.time()#记录开始时间 self.node_dfs()#执行dfs搜索算法 self.end = time.time()#记录结束时间 lab1 = tk.Label(frame_right, text="遍历路径数目:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f"{self.way_sum}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.05 + y0, width=100, height=30) lab2.place(relx=0.5, rely=0.05 + y0, width=100, height=30) lab1 = tk.Label(frame_right, text="求解花费时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f'{self.end - self.start:.4f} s', bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.10 + y0, width=100, height=30) lab2.place(relx=0.5, rely=0.10 + y0, width=100, height=30) lab = tk.Label(frame_right, text="自动求解优化路径-遍历", bg=RED, fg=BLACK, font=('微软雅黑', 20)) lab.place(rely=0.02, width=300, height=30) B = tk.Button(frame_right, text="返回", command=lambda: self.Solve_display()) B.place(relx=0.1, rely=y0, width=50, height=30) lab1 = tk.Label(frame_right, text="最短路径:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) # 根据遍历结果输出最短路径 way = "" for a in self.ans: way += d.Nodes[a][1] way += "->" way += d.Nodes[0][1] if not len(self.ans) == len(d.Nodes): way = "未找到联通路径" lab2 = tk.Label(frame_right, text=f"{way}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200, justify='left') lab1.place(relx=0.1, rely=0.2 + y0, width=80, height=30) lab2.place(relx=0.1, rely=0.25 + y0, width=200, height=100) # 如果有多条最短路径,则根据遍历结果依次输出 more = 0 way = '' for moreans in self.mutians: more += 1 if more > 1: way += '\n' way += str(more) + ': ' for a in moreans: way += d.Nodes[a][1] way += "->" way += d.Nodes[0][1] if more: lab1 = tk.Label(frame_right, text="其他最短路径:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = scrolledtext.ScrolledText(frame_right, width=50, height=5,bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab2.insert('end', way) lab2.configure(state=DISABLED) lab1.place(relx=0.1, rely=0.2 + y0 + 0.2, width=120, height=30) lab2.place(relx=0.1, rely=0.25 + y0 + 0.2, width=240, height=200) def greedy_panel(self): # 标记贪心路径 for w in frame_right.winfo_children(): w.destroy() # 清除右侧组件 lab = tk.Label(frame_right, text="自动求解贪心路径", bg=RED, fg=BLACK, font=('微软雅黑', 20)) lab.place(rely=0.02, width=300, height=30) y0 = 0.1 B = tk.Button(frame_right, text="返回", command=lambda: self.Solve_display()) B.place(relx=0.1, rely=y0, width=50, height=30) lab1 = tk.Label(frame_right, text="贪心法求得路径:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.2 + y0, width=150, height=30) # 求解贪心路径 self.node_greedy() lab1 = tk.Label(frame_right, text="求解花费时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.10 + y0, width=100, height=30) lab2 = tk.Label(frame_right, text=f'{self.end - self.start:.4f} s', bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab2.place(relx=0.5, rely=0.10 + y0, width=100, height=30) # 显示求解获得的贪心路径 way = "" for a in self.ans: way += d.Nodes[a][1] way += "->" way += d.Nodes[0][1] if not len(self.ans) == len(d.Nodes): way = "贪心法无法找到通路" lab2 = tk.Label(frame_right, text=f"{way}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200, justify='left') lab2.place(relx=0.1, rely=0.25 + y0, width=200, height=100) # 显示当前路径消耗的总成本与总时间 dis = 0 tim = 0 for edge in d.Edges: if edge[4] == True: dis += edge[6] tim += edge[7] lab1 = tk.Label(frame_right, text="路径距离/成本:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f'{dis}', bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.40 + y0, width=130, height=30) lab2.place(relx=0.5, rely=0.40 + y0, width=100, height=30) lab1 = tk.Label(frame_right, text="路径时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12)) lab2 = tk.Label(frame_right, text=f'{tim}', bg=BLUE, fg=BLACK, font=('微软雅黑', 12)) lab1.place(relx=0.1, rely=0.45 + y0, width=130, height=30) lab2.place(relx=0.5, rely=0.45 + y0, width=100, height=30) def check_condition(self, ways): con = 0 for w in ways: if d.Nodes[w][4] == 1: con += 1 if con == self.con: return 1 return 0 def dfs_condition(self, i, ways, sum, flag): if self.check_condition(ways) and d.Edges[G.node_edge(i, 0)][8] == 1 and d.Edges[G.node_edge(i, 0)][3] == 1: # 如果遍历的必经节点数目符合要求,则说明这是一条符合要求的路径 self.way_sum += 1#增加一个已搜索路径 sum += d.Edges[G.node_edge(i, 0)][6]#更新路径花费 if sum < self.minn:# 如果该路径的cost小于minn,则更新最短路径 self.ans.clear()#清除原答案 self.mutians.clear()#清除其他答案 self.ans = ways.copy()#将当前路径加入到答案中 self.minn = sum#更新最短路径 elif sum == self.minn:# 如果该路径的cost等于minn,则记录在mutians中 self.mutians.append(ways.copy())#将当前路径加入到其他路径数组中 for j in d.Edges:# 遍历该节点的所有路径,并且对所有可能路径进行尝试 if j[1] == i and flag[j[2]] == 0 and j[8] == 1 and j[3] == 1: ways.append(j[2])# 如果存在一节点还没被访问过,则将其加入搜索队列 flag[j[2]] = 1 self.dfs_condition(j[2], ways, sum + j[6], flag) flag[j[2]] = 0 ways.pop() if j[2] == i and flag[j[1]] == 0 and j[8] == 1 and j[3] == 1: flag[j[1]] = 1 ways.append(j[1]) self.dfs_condition(j[1], ways, sum + j[6], flag) ways.pop() flag[j[1]] = 0 return way_flag = 0#标记问题是否解决 def random_way(self, i, ways, sum, flag): if self.way_flag:#若已找到一条路径,则直接返回 return if len(ways) == len(d.Nodes) and d.Edges[G.node_edge(i, 0)][8] == 1\ and d.Edges[node_edge(i, 0)][3] == 1: # 如果遍历的节点数目符合要求,则说明这是一条符合要求的路径 sum += d.Edges[node_edge(i, 0)][6] # 更新当前路径长度 self.way_flag = 1#将问题标记为已解决 for way in ways: # 输出当前答案 print(way, end=' ') return cur_Edges = d.Edges.copy()# 随机打乱该点能接触到的路径 random.shuffle(cur_Edges) for j in cur_Edges: # 遍历该节点的所有路径,并且对所有可能路径进行尝试 if j[1] == i and flag[j[2]] == 0 and j[8] == 1 and j[3] == 1: # 如果存在一条路径,且对面节点还没被访问过,则将其加入搜索队列 ways.append(j[2])#将该点加入路径 flag[j[2]] = 1#将该点标记为已探索 self.random_way(j[2], ways, sum + j[6], flag)# 递归搜索路径 flag[j[2]] = 0#将该点标记为未探索 ways.pop()#将该点移除路径 if j[2] == i and flag[j[1]] == 0 and j[8] == 1 and j[3] == 1: flag[j[1]] = 1#将该点加入路径 ways.append(j[1])#将该点标记为已探索 self.random_way(j[1], ways, sum + j[6], flag)# 递归搜索路径 ways.pop()#将该点标记为未探索#将该点移除路径 flag[j[1]] = 0#将该点标记为未探索 return def dfs(self, i, ways, sum, flag): if len(ways) == len(d.Nodes) and d.Edges[node_edge(i, 0)][8] == 1\ and d.Edges[node_edge(i, 0)][3] == 1: # 如果遍历的节点数目符合要求,则符合要求 self.way_sum += 1 # 遍历路径的数目加一 sum += d.Edges[node_edge(i, 0)][6] # 更新当前路径长度 if sum < self.minn: # 如果该路径的cost小于minn,则更新最短路径 self.ans.clear() # 清除ans数组 self.mutians.clear() # 清除其他答案数组 self.ans = ways.copy() self.minn = sum # 更新最短路径 elif sum == self.minn: # 如果该路径的cost等于minn,则记录在mutians中 moreans = []#用于记录这条路径node_dfs_condition for way in ways:#将路径途径节点逐个加入 moreans.append(way) self.mutians.append(moreans)# 将该路径加入答案中 cur_Edges = d.Edges.copy()# 随机打乱该点能接触到的路径 random.shuffle(cur_Edges) for j in cur_Edges:# 遍历该节点的所有路径,并且对所有可能路径进行尝试 if j[1] == i and flag[j[2]] == 0 and j[8] == 1 and j[3] == 1: # 如果存在一条路径,且对面节点还没被访问过,则将其加入搜索队列 ways.append(j[2])#将该点加入路径 flag[j[2]] = 1#将该点标记为已探索 self.dfs(j[2], ways, sum + j[6], flag)# 递归搜索路径 flag[j[2]] = 0#将该点标记为未探索 ways.pop()#将该点移除路径 if j[2] == i and flag[j[1]] == 0 and j[8] == 1 and j[3] == 1: flag[j[1]] = 1#将该点加入路径 ways.append(j[1])#将该点标记为已探索 self.dfs(j[1], ways, sum + j[6], flag)# 递归搜索路径 ways.pop()#将该点标记为未探索#将该点移除路径 flag[j[1]] = 0#将该点标记为未探索 return def lcost_dfs_condition(self, i, ways, sum, flag): if i == self.curb:# 若该节点为目标节点 self.way_sum += 1#遍历路径数加一 if self.check_condition(ways):# 若遍历节点数符合要求 if sum < self.minn:#若路径花费更短,则更新答案 self.ans = ways.copy()#更新答案 self.minn = sum#更新最短路径 return for j in d.Edges:#遍历该点能到达的所有节点 if j[1] == i and flag[j[2]] == 0 and j[8] == 1 and j[3] == 1:#若该点未访问,则尝试访问 ways.append(j[2])#将该点加入路径 flag[j[2]] = 1#将该点标记为访问 self.lcost_dfs_condition(j[2], ways, sum + j[6], flag)#递归搜索路径 flag[j[2]] = 0#将该点移除路径 ways.pop()#将该点移除路径 if j[2] == i and flag[j[1]] == 0 and j[8] == 1 and j[3] == 1: flag[j[1]] = 1#将该点标记为访问 ways.append(j[1])#将该点加入路径 self.lcost_dfs_condition(j[1], ways, sum + j[6], flag)#递归搜索路径 ways.pop()#将该点移除路径 flag[j[1]] = 0#将该点标记为未访问 return def lcost_dfs(self, i, ways, sum, flag): # print(i) if i == self.curb: self.way_sum += 1 # print(ways, sum, self.minn) if sum < self.minn: self.ans = ways.copy() self.minn = sum return for j in d.Edges: if j[1] == i and flag[j[2]] == 0 and j[8] == 1 and j[3] == 1: ways.append(j[2]) flag[j[2]] = 1 self.lcost_dfs(j[2], ways, sum + j[6], flag) flag[j[2]] = 0 ways.pop() if j[2] == i and flag[j[1]] == 0 and j[8] == 1 and j[3] == 1: flag[j[1]] = 1 ways.append(j[1]) self.lcost_dfs(j[1], ways, sum + j[6], flag) ways.pop() flag[j[1]] = 0 return def ltime_dfs(self, i, ways, sum, flag): if i == self.curb:#若已经到达目标点,则结束搜索 self.way_sum += 1#遍历路径加一 if sum < self.minn:#若耗时少于最短时间 self.ans = ways.copy()#更新答案 self.minn = sum#更新最短时间 return for j in d.Edges:#遍历当前节点能到达的所有节点 if j[1] == i and flag[j[2]] == 0 and j[8] == 1 and j[3] == 1:#若该节点未遍历则尝试该条路径 ways.append(j[2])#将该节点加入路径 flag[j[2]] = 1#将该节点标记为已经过 self.ltime_dfs(j[2], ways, sum + j[7], flag)#进行递归搜索 flag[j[2]] = 0#将该节点标记为未经过 ways.pop() if j[2] == i and flag[j[1]] == 0 and j[8] == 1 and j[3] == 1: flag[j[1]] = 1#将该节点加入路径 ways.append(j[1])#将该节点标记为已经过 self.ltime_dfs(j[1], ways, sum + j[7], flag)#进行递归搜索 ways.pop()#将该节点移除路径 flag[j[1]] = 0#将该节点标记为未经过 def lowest_cost_dfs_condition(self): # 遍历 # 每两个点之间只保留最短路径 E.edge_del_all(1) self.ans.clear() self.way_sum = 0 self.con = 0 for n in d.Nodes: if n[4]: self.con += 1 for edge in d.Edges: edge[4] = False # for i in range(len(d.Nodes)): i = self.cura self.minn = float("inf") flag = [0] * len(d.Nodes) flag[i] = 1 self.lcost_dfs_condition(i, [i], 0, flag) for way in range(len(self.ans) - 1): d.Edges[G.node_edge(self.ans[way], self.ans[way + 1])][4] = True G.draw() def lowest_cost_dfs(self): # 遍历 # 每两个点之间只保留最短路径 E.edge_del_all(1) # E.newedge_del_all() self.way_sum = 0 self.ans = [] for edge in d.Edges: edge[4] = False # for i in range(len(d.Nodes)): i = self.cura self.minn = float("inf") flag = [0] * len(d.Nodes) flag[i] = 1 self.lcost_dfs(i, [i], 0, flag) for way in range(len(self.ans) - 1): d.Edges[G.node_edge(self.ans[way], self.ans[way + 1])][4] = True G.draw() def lowest_time_dfs(self): # 遍历 self.start = time.time()#记录开始时间 E.edge_del_all(2)#每两条边只保留时间最短路径(剪枝) self.way_sum = 0#初始化路径数目 self.ans = []#清空答案 for edge in d.Edges: edge[4] = False#清空标记 i = self.cura#初始化出发点 self.minn = float("inf")#初始化最短路径为无穷 flag = [0] * len(d.Nodes)#初始化已到达点 flag[i] = 1#将出发点标记为已到达 self.ltime_dfs(i, [i], 0, flag)#深度优先搜索确定答案 for way in range(len(self.ans) - 1):#标记途径路径 d.Edges[G.node_edge(self.ans[way], self.ans[way + 1])][4] = True self.end = time.time()#记录结束时间 G.draw()#重新绘图 def node_dfs_condition(self):# 遍历 E.edge_del_all(1)# 每两个节点之间只保留距离最短的一条 self.con = 0#初始化经过的必经点数目 self.way_sum = 0# 初始化遍历的节点数目 self.ans.clear()#清除答案数组 for node in d.Nodes:#计算必经点数量 if node[4] == 1: self.con += 1 for edge in d.Edges:#清空标记 edge[4] = False i = 0 self.minn = float("inf")#初始化最短路径为无穷 flag = [0] * len(d.Nodes)#初始化已经过数组 flag[i] = 1#将初始点标记为已经过 self.dfs_condition(i, [0], 0, flag)#开始遍历搜索合法路径 if not self.check_condition(self.ans):#若没找到合法路径在进行报告 tk.messagebox.askokcancel(title='结果', message='未找到联通路径') G.draw() return for way in range(len(self.ans) - 1):#逐个标记答案路径 d.Edges[G.node_edge(self.ans[way], self.ans[way + 1])][4] = True last = self.ans.pop()#弹出最后一个点 d.Edges[G.node_edge(last, i)][4] = True#链接首位形成环线 self.ans.append(last)#重新加入该点 G.draw()#绘图 def node_dfs(self): # 遍历 self.start = time.time() # 记录开始时间 E.edge_del_all(1)# 每两个节点之间只保留距离最短的一条 self.way_sum = 0# 初始化遍历的节点数目 for edge in d.Edges:#清空标记 edge[4] = False i = 0#起始点 self.minn = float("inf")#初始化最小值为正无穷 flag = [0] * len(d.Nodes)#初始化已经过点 flag[i] = 1#将起点标记为已经过 self.dfs(i, [0], 0, flag)#使用dfs算法搜索路径 if not len(self.ans) == len(d.Nodes):#若找不到符合要求的路径,则输出信息 tk.messagebox.askokcancel(title='结果', message='未找到联通路径') G.draw() return for way in range(len(self.ans) - 1):#标记一条路径 d.Edges[G.node_edge(self.ans[way], self.ans[way + 1])][4] = True last = self.ans.pop()#取出最后一个点 d.Edges[G.node_edge(last, i)][4] = True#将起始点与最终点链接形成环线 self.ans.append(last)#将最终点加回ans中 self.end = time.time() # 记录结束时间 G.draw() def node_greedy(self): # 贪心 self.start = time.time()#记录开始时间 self.ans.clear()#初始化答案列表 E.edge_del_all(1)# 两点间仅保留距离最短路径 for edge in d.Edges:#清空标记 edge[4] = False i = 0 # 起始点 ways = [i] flag = [0] * len(d.Nodes) # 初始化已经过点 cur = i#初始化起始点 sum = 0#初始化路径长度 flag[cur] = 1#将起始点标记为已经过 nxt = cur for ii in range(len(d.Nodes)): minn = float("inf")# 初始化最小值 for j in d.Edges:# 每一步选择当前最短的链接加到路径中去 if j[1] == cur and flag[j[2]] == 0 and j[6] < minn and j[8] == 1 and j[3] == 1: nxt = j[2] minn = j[6] if j[2] == cur and flag[j[1]] == 0 and j[6] < minn and j[8] == 1 and j[3] == 1: nxt = j[1] minn = j[6] if nxt != cur:#只要找到了新的路径,则加入路径中 ways.append(nxt) flag[nxt] = 1 sum += minn cur = nxt self.ans = ways.copy() # 如果找到的路径不合法,则表示贪心法无法求解得到合法路径 if (not len(self.ans) == len(d.Nodes)) or (d.Edges[G.node_edge(0, ways[len(ways) - 1])][3] == 0): tk.messagebox.askokcancel(title='结果', message='贪心法无法找到合法路径') self.ans.clear() return -1 for way in range(len(ways) - 1):#标记一条路径 d.Edges[G.node_edge(ways[way], ways[way + 1])][4] = True d.Edges[G.node_edge(ways[len(ways) - 1], i)][4] = True#标记起点终点形成环线 self.end = time.time()#记录结束时间 G.draw() # root.update() def check(self): # 检查是否存在最短路 find = [] for i in range(len(d.Nodes)): find.append(i) for edge in d.Edges: if edge[8] == 1 and edge[3] == 0: continue x = edge[1] y = edge[2] while not x == find[x]: x = find[x] while not y == find[y]: y = find[y] if x < y: find[y] = x else: find[x] = y flag = 1 for i in range(len(d.Nodes)): if not find[i] == find[0]: flag = 0 if flag: tk.messagebox.askokcancel(title='结果', message='该图存在最短路') else: tk.messagebox.askokcancel(title='结果', message='该图不能完全互通') if __name__ == '__main__': G.draw() solve = Solve() solve.Solve_display() mainloop()