图论求单源最短路 spfa算法(附模板)

来源:互联网 发布:产生随机数软件 编辑:程序博客网 时间:2024/05/16 01:18

今天我们来坑spfa_(:з」∠)_ 

SPFA shortest path faster algorithm 从字面理解就是比较快的最短路算法。这个算法可以看做是Bellman-Ford算法的队列优化(国际上一般不认可这个算法)。


算法的过程与Bellman-Ford相比,并不是无脑的进行松弛操作。因为可以进行松弛的点只会是其前导顶点成功松弛的点。所以我们利用一个队列来储存松弛成功的点。每次取出一个顶点看取其相邻的点查看是否可以松弛。这样的操作一直进行到队列内没有元素为止。(当然spfa无法处理负权图)


spfa有两种优化,small label first和large label last。不过我在oj上测试题目的时候优化的时间体现不是很明显。。。可能是数据大小的关系,所以底下就是一个裸的spfa,其中的sll策略可以利用priority_queue实现,这里就不写了。

spfa的复杂度最优为o(ke) k一般<=2,不过在某些精心构造的图中,其复杂度可以飙升至Bellman-Ford的o(ve)。所以有的时候要使用更加稳定dij算法。。。不过dij算法较spfa相比,代码量大,如果加上堆优化后,代码量会更大。所以还是尽可能的使用spfa算法求解单源最短路。


算法的具体实现我们用一个d[i]数组储存从源点到i的距离。算法开始时,我们将除d[source]以外的值都置为INF,并将source push到queue里。然后开始上述的操作,不断更新d[]和queue,直到queue为空时停止算法。(= =。。。描述貌似短了点。。。我感觉已经够了。。。卖个萌(◕ω<)☆ 


下面放出模板

vector<pair<int, int> > e[];//储存边int d[] = { 0 }; //表示到达的开销void spfa(int i) { // i 表示起点    priority_queue<int> q;    fill(d, d + MAX_N, INF);    d[i] = 0;    q.push(i);    while(!q.empty()) {        int tmp = q.top(); q.pop();        vector<pair<int, int> >::iterator iter;        for(iter = e[i].begin(); iter != e[i].end(); iter++) {            if(d[iter->first] > d[tmp] + iter->second)                d[iter->first] = d[tmp] + iter->second, q.push(iter->first);        }    }

不能更短了_(:з」∠)_

0 0
原创粉丝点击