问题就像Dijkstra's Single Source Shourtest Path with an extra edge with weight of 'w'。
您将获得一个无向加权图,它表示为邻接矩阵。找到图中起始节点和结束节点之间的最短路径。您可以在任何两个不直接相互连接的节点之间添加给定权重的最多一个边缘。
示例:
适用于start = 1
,finish = 4
,weight = 2
和
graph = [[0, 2, 0, 4, 0],
[2, 0, 1, 0, 0],
[0, 1, 0, 3, 0],
[4, 0, 3, 0, 1],
[0, 0, 0, 1, 0]]
输出应该是
shortestPathWithEdge(start, finish, weight, graph) == 3
。
我目前的解决方案使用Dijstra,但我根据有多少可能的边缘运行多次。我知道Dijstra,你可以获得所有节点的最短路径,但我似乎无法通过添加边缘连接来思考一种操作该数据的方法,而无需再次运行Dijstra算法。
图表可以是1000x1000。因此,使用大型矩阵,我的解决方案将太慢并且无法工作。
是否可以对Dijstra算法进行快速更新以处理其他边缘?
我的代码在下面,它可以工作但很慢。也许copy.copy
也会导致它比它应该慢得多。
import copy
def getDistances(graph):
##### GET DISTANCES FROM GRAPH
##### PLACE IN DICTIONARY FORM
distances = {}
edges = set()
for i, node in enumerate(graph):
distances[i+1] = {}
for j, distance in enumerate(node):
##### NO NEED TO GET DISTANCE TO ITSELF
if i != j:
distances[i+1][j+1] = distance
if distance == 0 and (i+1,j+1) not in edges and (j+1,i+1) not in edges:
##### ADD TO EDGES
edges.add((i+1,j+1))
return distances, edges
def dijstra(visited,unvisited,currentNode,currentDistance,distances,finish):
while True:
for neighbor, distance in distances[currentNode].items():
if distance == 0 or neighbor not in unvisited:
continue
newDistance = currentDistance + distance
if unvisited[neighbor] == None or unvisited[neighbor] > newDistance:
unvisited[neighbor] = newDistance
visited[currentNode] = currentDistance
del unvisited[currentNode]
if not unvisited:
break
candidates = [node for node in unvisited.items() if node[1]]
currentNode, currentDistance = sorted(candidates, key=lambda x: x[1])[0]
##### VISITED CONTAINS SHORTEST PATH TO ALL NODES
return visited[finish]
def shortestPathWithEdge(start, finish, weight, graph):
best = 10000000
nodes = { i+1 for i in range(len(graph)) }
distances, edges = getDistances(graph)
#####IF NO EXTRA EDGE
# visited = {}
# unvisited = { node:None for node in nodes}
# currentNode = start
# currentDistance = 0
# solution = dijstra(visited,unvisited,currentNode,currentDistance,distances,finish)
#####WITH AN EXTRA EDGE
solution = 10000000
for node1, node2 in edges:
_distances = copy.copy(distances)
_distances[node1][node2] = weight
visited = {}
unvisited = {node: None for node in nodes}
currentNode = start
currentDistance = 0
shortest2 = dijstra(visited, unvisited, currentNode, currentDistance, _distances, finish)
solution = min(solution,shortest2)
return solution
start = 1
finish = 4
weight = 2
graph = [[0, 2, 0, 4, 0],\
[2, 0, 1, 0, 0], \
[0, 1, 0, 3, 0], \
[4, 0, 3, 0, 1],\
[0, 0, 0, 1, 0]]
print("Answer:", shortestPathWithEdge(start, finish, weight, graph))