zoukankan      html  css  js  c++  java
  • SPFA算法

    2017-07-27  22:18:11

    writer:pprp

    SPFA算法实质与Bellman-Ford算法的实质一样,每次都要去更新最短路径的估计值。

    优化:只有那些在前一遍松弛中改变了距离点的值的点,才可能引起他们邻接点的距离估计值的改变;

    做法:使用队列来缩小搜索范围的;

    首先要将个点距离估计值设为+无穷,并将起始点加入队列。如果通过队列中的点i到相邻点j的距离小于原来到点j的距离,

    即d[j]>d[i]+w[i][j]则d[j] = d[i] + w[i][j];将j点加入队列。当队列为空的时候,才能说明一丘处从起始点到任一点的最短距离。              

    为了防止同一个点多次出现在队列里,需要对该点做标记以确定带点是够存在于队列中;

    注意点:仅当图不存在负权回路,SPFA才能正常工作;

    判断负权回路方法有很多:

    1. 记录每个节点的进队次数,超过n说明有负权;
    2. 记录这个节点在路径所处位置ord[i],每次更新的时候ord[i] = dor[x]+1;超过n证明有负权

    代码如下:

    #include <iostream>
    #include <queue>
    
    using namespace std;
    
    const int INF = 99999999;
    
    struct node
    {
        int n;
        int v;
        node*next;
        node()
        {
            n = 0;
            next = NULL;
        }
    }*e[1001];       //存放每一个点到别的点的边
    int d[1001];     //估计值
    bool c[1001];    //判断该顶点是否存在与队列中
    queue<int> qu;  //队列
    int n,m;         //n是顶点数,m是边的数目
    
    void init()
    {
        cin >> n >> m;
        node*p;
        int x,y,v;
        for(int i = 1; i <= n; i++)
        {
            cin >> x >> y >> v;
            p = new node();
            p->n = y;
            p->v = v;
            if(e[x]==NULL)
                e[x] = p;
            else
            {
                p->next = e[x]->next;
                e[x]->next = p;
            }
        }
    }
    
    void spfa(int x)
    {
        int i;
        node*p;
        qu.push(x);     //  将起始点加入队列
        for(i = 1; i <= n; i++)
            d[i] = INF;
        d[x] = 0;
        for(i =1; i<=(int)qu.size(); i++)    //读取队列
        {
            p = e[qu.front()];    //和qu相连的边
            while(p!=NULL)
            {
                if(d[qu.front()]+p->v < d[p->n])
                {
                    d[p->n] = d[qu.front()]+p->v; //更新距离
                    if(!c[p->n])          //如果p->n点没有在队列里
                    {
                        c[p->n] = 1;
                        qu.push(p->n);
                    }
                }
                p = p->next;        //下一个点
            }
            c[qu.front()]=0;   
         qu.pop(); //该点出队 }
    for(i=1; i<=n; i++) cout <<d[i]<<" "; cout << endl; } int main() { init(); spfa(1); return 0; }

    之后还要再看一下

  • 相关阅读:
    [Codeforces-div.1 809C] Find a car
    [Codeforces-div.1 55D] Beautiful numbers
    [BZOJ3598] [Scoi2014]方伯伯的商场之旅
    [BZOJ3131] [Sdoi2013]淘金
    [BZOJ2757] [SCOI2012]Blinker的仰慕者
    [BZOJ3329] Xorequ
    [POJ3744] Scout YYF I
    angular-file-upload 回显已上传的文件
    angular-file-upload 限制文件上传个数 获取已上传文件队列
    angular-file-upload 一款好用的文件上传组件,基本应用
  • 原文地址:https://www.cnblogs.com/pprp/p/7247713.html
Copyright © 2011-2022 走看看