算法背后的直觉来计算DAG中每个顶点的单源最短路径

时间:2016-05-16 12:17:03

标签: algorithm graph graph-theory

算法如下:

  

算法首先通过拓扑排序dag(参见第22.4节)对顶点施加线性排序。如果dag包含从顶点u到顶点v的路径,则u在拓扑排序中位于v之前。我们只按拓扑排序顺序对顶点进行一次传递。当我们处理每个顶点时,我们放松离开顶点的每条边。

有人可以告诉我背后的直觉吗?使用这种直觉,请告诉我们如何找到最长的路径,只是否定边权和运行算法

我们不能使用Dijkstra算法,因为允许边具有负权重。

3 个答案:

答案 0 :(得分:1)

如果您已经知道可以在其之前的所有顶点的最短路径,则查找到顶点的最短路径很容易。如果您已经知道可以在其之前的所有顶点的最长路径,那么在DAG中查找到顶点的最长路径很容易。

以拓扑顺序处理顶点可确保在到达顶点时,您已经处理了可以在它之前的所有顶点。

Dijkstra算法对于可以包含循环的图是必要的,因为它们不能进行拓扑排序。

答案 1 :(得分:1)

您的问题与DAG中的单源最短路径问题(SSSP)有关。 图的拓扑排序表示图的线性排序。允许以拓扑顺序(从左到右)处理所有顶点,并且将使用弛豫属性找到所有最短路径。该算法的运行时间为O(|V| + |E|),其中V是一组顶点,E是一组边。

如果要查找最长路径(或关键路径),可以使用下一个变体:

第一种方法是否定边权重。具有最小负值的路径将给出最长路径(但对于算法,它仍将是最小路径)。我们可以这样做,因为拓扑排序可以使用负边缘权重。

第二种方法是改变放松步骤:

1. Cost of each vertex is initialized to negative infinity
2. Change the relaxation step:
  if d(v) < d(u) + w
  then d(v) = d(u) + w
  else d(v) is remains unchanged

where d - the distance;
u, v - vertices;
w - weight on edge (u, v).

在解决SSSP问题的一般情况下,有Dijkstra和Bellman-Ford算法。主要区别在于Bellman-Ford算法为图中的任何权重计算SSSP,并且可以检测图中的负权重周期,但Dijkstra算法可以使用正权重。

有关详细信息,请参阅Shortest Paths

答案 2 :(得分:0)

拓扑排序确保我们在从源头开始旅行时选择最先出现的节点,这反过来又将确保每个节点至少有一个可以从源头到达的条件。

for (int i = 0; i < N; i++)
    if (visited[i] == false)
        topologicalSortUtil(i, visited, stack, adj);

for (int i = 0; i < N; i++)
    dist[i] = Integer.MAX_VALUE;
dist[s] = 0;

while (stack.empty() == false)
{
    int node = (int)stack.pop();

    if (dist[node] != Integer.MAX_VALUE)
    {
        enter code here  for(Pair it: adj.get(node)) {
            if(dist[node] + it.getWeight() < dist[it.getV()]) {
                dist[it.getV()] = dist[node] + it.getWeight(); 
            }
        }
    }
}

当我们设置 dist[src] = 0 时,它将从那里开始,条件 dis[node] != infinity 不会让除 src 之外的任何其他节点首先进入该条件。因为在 src 之前的拓扑排序注释将被丢弃。