图论算法-最短路径算法
Posted geekfx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图论算法-最短路径算法相关的知识,希望对你有一定的参考价值。
无权最短路径
从图G中,选择s为开始的点,从s到s的最短路径是长为0的路径,将这个信息做个标记;然后开始寻找所有与s距离为1的顶点,将这些顶点做标记;然后开始找出从s出发最短路径恰为2的顶点;直到所有顶点已经被计算。
这种搜索一个图的方法称为广度优先搜索(breadth-first search)。该方法按层处理顶点:距开始点最近的那些顶点首先被赋值,而最远的那些顶点最后被赋值。这很像对树的层序遍历(level-order traversal)。
伪代码
void Unweighted(Table T) // Assume T is intialized
{
int CurrDist;
Vertex v,w;
for(CurrDist = 0; CurrDist < NumVertex; CurrDist++)
for each vertex v // 使用 v 遍历每个点
if (!T[v].know && T[v].Dist == CurrDist)
{
T[v].know = True; // 表示表 T 中 v 顶点已被访问过
for each w adjacency to v // 使用 w 遍历 v 的所有邻接点
if(T[w].dist == Infinity) // 表示顶点 w 的距离是否已被更新过
{
T[w].dist = CurrDist + 1;
T[w].path = v;
}
}
}
由于双层嵌套for循环,因此该算法的运行时间为(O(left | V ight |^2))。这个效率明显地低,因为尽管所有的顶点早就被访问过(表 T 中know为True),但是外层循环还是要继续。
使用类似于拓扑排序的做法来排除这种低效性,使用一个队列优化,在迭代开始的时候,队列只含有距离为(CurrDist)的那些顶点。我们添加(CurrDist+1)的那些邻接顶点时,由于它们自队尾入队,因此这就保证它们直到所有距离为(CurrDist)的那些邻接顶点都被处理之后才被处理。
伪代码
void Unweighted(Table T)
{
Queue Q;
Vertex v, w;
Q = CreateQueue(NumVertex);
MakeEmpty(Q);
// Enqueue the start vertex S, determined elsewhere
Enqueue(S, Q);
while(!IsEmpty(Q))
{
v = Dequeue(Q);
for each w adjacency to v
if(T[w].dist == Infinity)
{
T[w].dist = T[v].dist + 1;
t[w].path = v;
Enqueue(w, Q);
}
}
DisposeQueue(Q); // Free the memory
}
Dijkstra算法
解决单源最短路径问题的一般方法叫Dijkstra算法。这个有历史的解法是贪婪算法(greedy algorithm)最好的例子。贪婪算法一般地分阶段求解一个问题,在每个阶段它都把当前出现的当作是最好的去处理。
在每个阶段,Dijkstra算法选择一个顶点(v),它在所有未知顶点中具有最小的(d_v),同时算法声明从(s)到(v)的最短路径是已知的。阶段的其余部分有(d_w)值的更新的工作组成。
伪代码
void Dijkstra(Table T)
{
Vertex v, w;
for(;;)
{
v = smallest unknown distance vertex;
if(v == NotAVertex)
break;
T[v].known = True;
for each w adjacency to v
if(!T[w].known)
if(T[v].dist + Cvw < T[w].dist)
{
// Update w
Decrease(T[w].dist to T[v].dist + Cvw);
T[w].path = v;
}
}
}
只要没有边的值为负,该算法总能够顺利完成。如果任何一边出现负值,则算法可能得出错误的答案。总的运行时间为(O(left | V ight |^2))。
具有负边值的图
如果图出现负边值,那么Dijkstra算法是行不通的。
把带权和不带权的算法结合起来将会解决这个问题。开始,我们把开始的顶点s放入到队列中,然后,在每一阶段我们让一个顶点v出队。找出所有与v邻接的顶点w,使得d_w>d_v+c_{v,w}。然后更新,d_w和p_w,并在w不在队列中的时候把它放到队列中。
伪代码
void WeightedNegative(Table T)
{
Queue Q;
Vertex v, w;
Q = CreateQueue(NumVertex);
MakeEmpty(Q);
while(!IsEmpty(Q))
{
v = Dequeue(Q);
for each w adjacency to v
if(T[v].dist + Cvw < T[w].dist)
{
// Update w
T[w].dist = T[v].dist + Cvw;
T[w].path = v;
if(w is not already in Q)
Enqueue(w, Q);
}
}
DisposeQueue(Q); // Free the memory
}
以上是关于图论算法-最短路径算法的主要内容,如果未能解决你的问题,请参考以下文章