You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2.1 KiB
2.1 KiB
spfa
和bfs
的区别
spfa
在形式上和bfs
非常类似,不同的是bfs
中一个点出了队列就不可能重新进入队列,但是spfa
中一个点可能在出队列之后再次被放入队列,也就是一个点松弛过其它的点之后,过了一段时间可能本身被松弛,于是要再次用来松弛其它的点,这样反复迭代下去。
一、bfs
算法模板
queue<int> q;
st[1] = true; // 表示1号点已经被遍历过
q.push(1);
while (q.size()){
int u = q.front();
q.pop();
for (int i = h[u]; ~i; i = ne[i]){
int j = e[i];
if (!st[j]){
st[j] = true; // 表示点j已经被遍历过
q.push(j);
}
}
}
二、spfa
算法模板
int spfa(){
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
queue<int> q;
q.push(1);
st[1] = true;
while (q.size()){
auto u = q.front();
q.pop();
st[u] = false;
for (int i = h[u]; ~i; i = ne[i]){
int j = e[i];
if (dist[j] > dist[u] + w[i]){
dist[j] = dist[u] + w[i];
// 如果队列中已存在j,则不需要将j重复插入
if (!st[j]){
q.push(j);
st[j] = true;
}
}
}
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
在spfa
中一个点的距离 可能被多次更新,因为有权值为 负数 的边,而Dijktra
,bfs
所有边的 权值都非负,且每次更新其他点的距离的时候,都取的是当前未确定和起点距离的点中距离最小的点,所以当有其他路径通向这个点的时候不管是一条还是几条边距离一定都大于你选的这个边的距离,所以此时这个点到起点的距离就已经被确定不会改变了,而spfa
允许存在负边,可能存在一条路径第一段权值较大,但是后几段距离是负数,就会更新dist
了,所以在spfa
算法中,在出队后将st[t]
标记为false
,使得以后还可以入队来更新路径。