You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

878 lines
42 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# -*- 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
# 根据已有数据获得ab点的编号
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 = []# 使用并查集来检测ab点是否互通
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()