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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

spfabfs的区别

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,使得以后还可以入队来更新路径。