码迷,mamicode.com
首页 > 编程语言 > 详细

算法基础 - 单源点最短路径SPFA

时间:2016-05-08 06:51:29      阅读:299      评论:0      收藏:0      [点我收藏+]

标签:

SPFA是非常简单的最短路径算法,思想就是从起点开始,进行宽度优先搜索,不断松弛S点到其他相邻点的距离。如果松弛了点B,则把点B放到队列里。假如点B已经在队列里了,就不要放了,判断在不在队列可以用个数组来表示。

引用一段hihocoder上的解释:

构造一个队列,最开始队列里只有(S, 0)——表示当前处于点S,从点S到达该点的距离为0,然后每次从队首取出一个节点(i, L)——表示当前处于点i,从点S到达该点的距离为L,接下来遍历所有从这个节点出发的边(i, j, l)——表示i和j之间有一条长度为l的边,将(j, L+l)加入到队尾,最后看所有遍历的(T, X)节点中X的最小值就是答案咯~”小Ho对于搜索已经是熟稔于心,张口便道。
SPFA算法呢,其实某种意义上就是宽度优先搜索的优化——如果你在尝试将(p, q)加入到队尾的时候,发现队列中已经存在一个(p, q‘)了,那么你就可以比较q和q’:如果q>=q‘,那么(p, q)这个节点实际上是没有继续搜索下去的必要的——算是一种最优化剪枝吧。而如果q < q‘,那么(p, q‘)也是没有必要继续搜索下去的——但是它已经存在于队列里了怎么办呢?很简单,将队列中的(p, q‘)改成(p, q)就可以了!”

“那我该怎么知道队列中是不是存在一个(p, q‘)呢?”
维护一个position[1..N]的数组就可以了,如果不在队列里就是-1,否则就是所在的位置!”

“所以说这本质上就是宽度优先搜索的剪枝咯?”小Ho问道。
小Hi笑道:“怎么可能!SPFA算法其实是BELLMAN-FORD算法的一种优化版本,只不过在成型之后可以被理解成为宽度优先搜索的!这个问题,我们会在之后好好讲一讲的!

代码如下:

#include <iostream>
#include <cstring>
#include <string>
#include <queue>

using namespace std;

struct Node{
    int val;
    int len;
    Node * next;
    Node():val(-1),len(-1), next(NULL){}
    Node(int x, int le): val(x), len(le), next(NULL){}
};

long long SPFA(Node node[], int M, int S, int T){
    queue<int> st;
    st.push(S);
    int flag[M+5];
    long long dist[M+5];
    for(int i = 0; i < M+5; i++){
        flag[i] = 0;
        dist[i] = -1;
    }
    dist[S] = 0;
    flag[S] = 1;
    while(!st.empty()){
        int cur = st.front();
        st.pop();
        flag[cur] = 0;
        Node * temp = node[cur].next;
        while(temp != NULL){
            if(dist[temp->val] == -1 || dist[temp->val] > (dist[cur]+temp->len)){
                dist[temp->val] = dist[cur]+temp->len;
                if(flag[temp->val] == 0){
                    st.push(temp->val);
                    flag[temp->val] = 1;
                }
            }
            temp = temp->next;
        }
    }
    return dist[T];
}

int main(){
    int M,N,S,T;
    // M 顶点个数, N 边个数, S起点, T 终点
    while(cin>>M>>N>>S>>T){
        Node node[M+5];
        int st, en, le;
        for(int i = 0; i < N;i++){
            cin>>st>>en>>le;
            //st边起点 en边终点 le边长度
            Node * temp = new Node(en,le);
            temp->next = node[st].next;
            node[st].next = temp;

            /*如果是无向图加上这三条语句
            temp = new Node(st,le);
            temp->next = node[en].next;
            node[en].next = temp;
            */
        }
        cout<<SPFA(node, M, S, T)<<endl;
    }
}

大致如上

算法基础 - 单源点最短路径SPFA

标签:

原文地址:http://blog.csdn.net/alps1992/article/details/51341071

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!