在图表中找到成本最高的路径的最佳方法

时间:2013-06-14 13:47:39

标签: algorithm graph graph-algorithm

我有一个有向无环图,每个顶点的权重都是> = 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的每条路径,如上例所示,然后,我选择总和最大的路径。我担心这种方法真的很天真。

有更好的算法吗?这个问题可以减少到另一个吗?

3 个答案:

答案 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

因为权重驻留在顶点上,所以在计算之前,您可能希望将权重移动到顶点的边缘。