bellman-ford and SPFA

来源:互联网 发布:hp1005扫描软件 编辑:程序博客网 时间:2024/05/21 19:28

第一种算法bellman-ford算法


这段文字来自lrj书的截图

其中解释一下如果一个图是DAG如何用拓扑序来计算d[i];

因为无环图的话求一个顶点的最短路不用考虑这个顶点后面的点,所以就可以用拓扑序来用计算一个点后面的所有点的距离

一般情况

c被a更新一次最短路为3,最后被b更新最短路为2;

算法实现就是先用拓扑排序得到一个队列,再依次用队列中的顶点求其所有邻接点的最短路;复杂度是O(v+e)拓扑排序是v,求最短路是e。

如果不是DAG图

如果是DAG图,就不知道从哪儿开始更新,所以要遍历所有边来更新,直到最短路不再改变,从上面的DAG图我们可以知道,按照类似拓扑顺序的更新最短路是最快的,反之最慢这样最多就是外层循环V-1次。

复杂度O(v*e)

#include <iostream>#include<cstdio>using namespace std;const int N=1e3;const int M=1e3;const int INF=0x1ffff;int n,m;struct edge{        //存放边(起点,终点,弧(边)长)的结构体    int from,to,cost;    void set(int a,int b,int c){        from=a;to=b;cost=c;    }};edge e[M];          //边数组 int d[N];           //起点到每个其他顶点最短距离辅助数组int main(){    freopen("in.txt","r",stdin);    cin>>n>>m;    int a,b,c;    for(int i=0;i<m;i++){        cin>>a>>b>>c;        e[i].set(a,b,c);    }    for(int i=1;i<=n;i++){        d[i]=INF;    }    printf("输入x,y\n");    int x,y;    cin>>x>>y;    d[x]=0;                 //28行~这里是初始化,d[i]=INF,d[起点]=0;    while(true){            //外层循环最多循环n-1次,在图为线性的时候取最大值        bool change=false;        for(int i=0;i<m;i++){   //遍历所有边            edge ed=e[i];            if(d[ed.from]!=INF&&d[ed.to]>d[ed.from]+ed.cost){   //起点能到中间点,且中间点加入后距离变小                change=true;                d[ed.to]=d[ed.from]+ed.cost;            }        }        if(!change)break;    }    printf("the minidistance between %d and %d is %d\n",x,y,d[y]);    return 0;}

如图,如果是1 2 3 4 四个点的话,顺序遍历一次边就结束了,逆序遍历的话,(3,4),(2,3)都无效,然后加入(1,2) 以此类推。

SPFA算法(摘抄)

先讲一下SPFA的大致思想

算法大致流程是用一个队列来进行维护。 初始时将源加入队列。 每次从队列中取出一个元素,并对所有与他相邻的点进行松弛,若某个相邻的点松弛成功,如果该点没有在队列中,则将其入队。 直到队列为空时算法结束。

判断有无负环:如果某个点进入队列的次数超过V次则存在负环(SPFA无法处理带负环的图)

SPFA算法有两个优化算法 SLF 和 LLL: SLF:Small Label First 策略,设要加入的节点是j,队首元素为i,若dist(j)<dist(i),则将j插入队首,否则插入队尾。 LLL:Large Label Last 策略,设队首元素为i,队列中所有dist值的平均值为x,若dist(i)>x则将i插入到队尾,查找下一元素,直到找到某一i使得dist(i)<=x,则将i出对进行松弛操作。 SLF 可使速度提高 15 ~ 20%;SLF + LLL 可提高约 50%。 在实际的应用中SPFA的算法时间效率不是很稳定,为了避免最坏情况的出现,通常使用效率更加稳定的Dijkstra算法。个人觉得LLL优化每次要求平均值,不太好,为了简单,我们可以之间用C++STL里面的优先队列来进行SLF优化




原创粉丝点击