算法如下:
算法首先通过拓扑排序dag(参见第22.4节)对顶点施加线性排序。如果dag包含从顶点u到顶点v的路径,则u在拓扑排序中位于v之前。我们只按拓扑排序顺序对顶点进行一次传递。当我们处理每个顶点时,我们放松离开顶点的每条边。
有人可以告诉我背后的直觉吗?使用这种直觉,请告诉我们如何找到最长的路径,只是否定边权和运行算法
我们不能使用Dijkstra算法,因为允许边具有负权重。
答案 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 之前的拓扑排序注释将被丢弃。