B e l l m a n − F o r d Bellman-Ford Bellman−Ford算法和 S P F A SPFA SPFA算法
dijkstra能应用于带负边权的图,只能用 O ( V E ) O(VE) O(VE)内解决问题的Bellman-ford与spfa算法。
B e l l m a n − F o r d Bellman-Ford Bellman−Ford
对于给定的一张有向图若对于图中的某一条边
(
x
,
y
,
z
)
(x,y,z)
(x,y,z),有dist[y]≤dist[x]+z成立,则称该边满足三角形不等式。若所有边都满足三角形不等式,则dist数组就是各点的最短路径长。
它的流程如下:
1.扫描所有边
(
x
,
y
,
z
)
(x,y,z)
(x,y,z),若dist[y]>dist[x]+z,则用dist[x]+z更新dist[y]。
2.重复步骤1,一般n-1遍就可以更新完毕,如果在第n次还有不满足三角形不等式的边,那么就说明有负环出现。
S h o r t e s t P a t h F a s t A l g o r i t h m Shortest Path Fast Algorithm ShortestPathFastAlgorithm
其流程如下:
1.建立一个队列, 最初队列中只含有起点1.
2.取出队头节点下,扫描它的所有出边
(
x
,
y
,
z
)
(x,y,z)
(x,y,z),若dist[y]>dist[x]+z,则使用dist[x]+z去更新 dist[y],同时若y不在队列中,则把y入队(用布尔数组标记)。
3.重复上述步骤,直至队列为空。
void spfa(){
memset(d, 0x3f, sizeof(d));//dist数组
memset(v, 0, sizeof(v));//是否在队列中
d[1] = 0;v[1] = 1;//因为1号点进入了队列
q.push(1);
while(q.size()){
// 取出队头
int x = q.front();q.pop();
v[x] = 0;//这时候队头不在队列中,所以记为0
//扫描所有出边
for(int i = head[x]; i; i = Next[i]){
int y = ver[i], z = edge[i];
if(d[y] > d[x]+z){
//更新,把新的二元组插入堆
d[y] = d[x] + z;
if(!v[y]) q.push(y), v[y] = 1;
}
}
}
}
无注释版
void spfa(){
memset(d, 0x3f, sizeof(d));
memset(v, 0, sizeof(v));
d[1] = 0;v[1] = 1;
q.push(1);
while(q.size()){
int x = q.front();q.pop();
v[x] = 0;
for(int i = head[x]; i; i = Next[i]){
int y = ver[i], z = edge[i];
if(d[y] > d[x]+z){
d[y] = d[x] + z;
if(!v[y]) q.push(y), v[y] = 1;
}
}
}
}