我有一个有向无环图,每个顶点的权重都是> = 0.有一个顶点是图的“起点”,另一个顶点是图的“结束”。我们的想法是找到从开始到结束的路径,其顶点权重之和越大。例如,我有下一个图表:
I(0) -> V1(3) -> F(0)
I(0) -> V1(3) -> V2(1) -> F(0)
I(0) -> V3(0.5) -> V2(1) -> F(0)
最昂贵的路径是I(0) - > V1(3) - > V2(1) - > F(0),成本为4。
现在,我正在使用BFS来枚举从I到F的每条路径,如上例所示,然后,我选择总和最大的路径。我担心这种方法真的很天真。
有更好的算法吗?这个问题可以减少到另一个吗?
答案 0 :(得分:3)
您可以执行拓扑排序,然后遍历拓扑排序返回的顶点列表,从起始顶点到结束顶点并计算成本。对于当前顶点的每个有向边检查是否可以提高目标顶点的成本,然后移动到下一个顶点。最后,[end_vertex]将包含结果。
class grph:
def __init__(self):
self.no_nodes = 0
self.a = []
def build(self, path):
file = open(path, "r")
package = file.readline()
self.no_nodes = int(package[0])
self.a = []
for i in range(self.no_nodes):
self.a.append([10000] * self.no_nodes)
for line in file:
package = line.split(' ')
source = int(package[0])
target = int(package[1])
cost = int(package[2])
self.a[source][target] = cost
file.close()
def tarjan(graph):
visited = [0] * graph.no_nodes
path = []
for i in range(graph.no_nodes):
if visited[i] == 0:
if not dfs(graph, visited, path, i):
return []
return path[::-1]
def dfs(graph, visited, path, start):
visited[start] = 1
for i in range(graph.no_nodes):
if graph.a[start][i] != 10000:
if visited[i] == 1:
return False
elif visited[i] == 0:
visited[i] = 1
if not dfs(graph, visited, path, i):
return False
visited[start] = 2
path.append(start)
return True
def lw(graph, start, end):
topological_sort = tarjan(graph)
costs = [0] * graph.no_nodes
i = 0
while i < len(topological_sort) and topological_sort[i] != start:
i += 1
while i < len(topological_sort) and topological_sort[i] != end:
vertex = topological_sort[i]
for destination in range(graph.no_nodes):
if graph.a[vertex][destination] != 10000:
new_cost = costs[vertex] + graph.a[vertex][destination]
if new_cost > costs[destination]:
costs[destination] = new_cost
i += 1
return costs[end]
输入文件:
6
0 1 6
1 2 2
3 0 10
1 4 4
2 5 9
4 2 2
0 2 10
答案 1 :(得分:2)
由于你的图表没有周期 * ,你可以否定边缘的权重,然后运行Bellman-Ford's algorithm。
<小时/> * Floyd-Warshall和Bellman-Ford等最短路径算法不适用于具有负周期的图形,因为您可以通过保持负循环来构建任意小权重的路径。
答案 2 :(得分:1)
一般来说,最长路径问题是NP难的,但由于图是DAG,因此可以通过首先否定权重然后执行最短路径来解决。请参阅here。
因为权重驻留在顶点上,所以在计算之前,您可能希望将权重移动到顶点的边缘。