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

    适用于:
    稀疏图(侧重于对边的处理)。

    时间复杂度:
    O(KE),K是常数,平均值为二,E是边数。(因为和边有关,所以不适于稠密图)

    来源:
    SPFA是Bellman-Ford算法的一种队列实现,减少了不必要的冗余计算。 
    这个算法简单地说就是队列优化的Bellman-Ford,利用了每个点不会更新次数太多的特点发明的此算法。 
    SPFA在形式上和广度优先搜索非常类似,不同的是广度优先搜索中的一个点出了队列就不可能重新进入队列,但是SPFA中的一个点可能在出队列之后再次被放入队列,也就是说一个点修改过其他的点之后,过了一段时间可能会获得更短的路径,于是再次用来修改其他的点,这样反复进行下去。

    优化方法:
    1.循环队列(可以降低队列大小) 
    2.SLF:Small Label First 策略,设要加入的节点是j,队首元素为i,若dist(j) < dist(i),则将j插入队首,否则插入队尾。

    if(!vis[temp])
    {
        if(dis[q[head + 1]] < dis[temp])  //注意小于号不要写反,否则时间会爆
          {
            tail = (++tail - 1) % qxun + 1;
            q[tail] = temp;
          }
        else
          {
            q[head] = temp;
            if(--head == 0) head = qxun;
          }
        vis[temp] = 1;
    }

    3.LLL:Large Label Last 策略,设队首元素为i,每次弹出时进行判断,队列中所有dist值的平均值为x,若dist(i)>x则将i插入到队尾,查找下一元素,直到找到某一i使得dist(i)<=x,则将i出对进行松弛操作。

    实现:
    (伪代码)

    dis[i]记录从起点s到i的最短路径,w[i][j]记录连接i,j的边的长度,pre[v]记录前趋。
    team[1..n]为队列,头指针head,尾指针tail。
    布尔数组exist[1..n]记录一个点是否现在存在队列中。
    初始化:dis[s] = 0, dis[v] = oo(v != s), memset(exist, false, sizeof(exist));
    起点入队 team[1] = s; head = 0; tail = 1; exist[s] = true;
    do
      {
        1.头指针向下移一位,取出指向的点u。
        2.exist[u] = false; 已经被取出了队列。
        3.for与u相连的所有点v  //注意不要去枚举所有点,用链式前向星存储
          if(dis[v] > dis[u] + w[u][v])
            {
              dis[v] = dis[u] + w[u][v];
              pre[v] = u;
              if(!exist[v]) //队列中不存在v点,v入队
                {
                  尾指针下移一位,v入队;
                  exist[v] = true;
                }
              }
      }while(head < tail);


    --------------------- 

  • 相关阅读:
    机器学习系列(4) 线性回归
    MYSQL系列(5) 电商常用指标查询
    MYSQL系列(4) 关于时间函数的一些写法
    快速排序
    选择排序
    希尔排序
    直接插入排序
    冒泡排序
    Java修饰符大汇总
    字符串实现大数的相加
  • 原文地址:https://www.cnblogs.com/DWVictor/p/10282794.html
Copyright © 2011-2022 走看看