zoukankan      html  css  js  c++  java
  • SPFA的两个优化

    评测题:洛谷【模板】单源最短路径

    不加任何优化:

     1 queue<int>q;
     2 void spfa(ll s)
     3 {
     4     for(ll i=1;i<=n;i++) d[i]=(ll)(2147483647);
     5     d[s]=0;q.push(s);v[s]=1;
     6     while(!q.empty())
     7     {
     8         ll ff=q.front();q.pop();v[ff]=0;
     9         for(ll i=h[ff];i;i=e[i].ne)
    10         {
    11             ll rr=e[i].v;
    12             if(d[rr]>d[ff]+e[i].c)
    13             {
    14                 d[rr]=d[ff]+e[i].c;
    15                 if(!v[rr]) q.push(rr),v[rr]=1;
    16                 
    17             }
    18         }
    19     }
    20 }
    View Code

    ==================================================

    优化1(SLF:Small Label First):

    使用双端队列(详见代码注释)

    证明:显然定理 

     1 deque<ll>q;
     2 void spfa(ll s)
     3 {
     4     for(ll i=1;i<=n;i++) d[i]=(ll)(2147483647),v[i]=0;
     5     d[s]=0;q.push_back(s);v[s]=1;//双端队列 
     6     while(!q.empty())
     7     {
     8         ll ff=q.front();q.pop_front();v[ff]=0;
     9         for(ll i=h[ff];i;i=e[i].ne)
    10         {
    11             ll rr=e[i].v;
    12             if(d[rr]>d[ff]+e[i].c)
    13             {
    14                 d[rr]=d[ff]+e[i].c;
    15                 if(!v[rr]) 
    16                 {
    17                     if(q.empty() || d[rr]>=d[q.front()]) q.push_back(rr);
    18                     else q.push_front(rr);
    19                     //如果当前点的dis<队列首的dis,就把当前点放在队列首
    20                     //让它优先去更新其他点,减少入队次数
    21                     //注意,特殊情况,如果队列为空的话,要放在队列为,不然会RE 
    22                     v[rr]=1;
    23                 }
    24             }
    25         }
    26     }
    27 }
    View Code

    ==================================================================================

    优化2(LLL:Large Label Last):

    使用双端队列,sum为队列中所以元素的dis和,o为队列中元素个数

    即x=sum/o;

    对于当前点i,如果dis[i]>=x  则将点i插入到队列尾,否则放到队列首。

    证明:不会。

     1 deque<int>q;
     2 void spfa(ll s)
     3 {
     4     for(ll i=1;i<=n;i++) d[i]=(ll)(2147483647);
     5     d[s]=0;q.push_back(s);v[s]=1;
     6     sum+=d[s];o++;
     7     while(!q.empty())
     8     {
     9         ll ff=q.front();q.pop_front();v[ff]=0;
    10         sum-=d[ff];o--;
    11         for(ll i=h[ff];i;i=e[i].ne)
    12         {
    13             ll rr=e[i].v;
    14             if(d[rr]>d[ff]+e[i].c)
    15             {
    16                 d[rr]=d[ff]+e[i].c;
    17                 if(!v[rr]) 
    18                 {
    19                     v[rr]=1;
    20                     if(q.empty() || o*d[rr]>=sum) q.push_back(rr);
    21                     else q.push_front(rr);
    22                     //注意,特殊情况,如果队列为空的话,要放在队列为,不然会RE 
    23                 }
    24                 
    25             }
    26         }
    27     }
    28 }
    View Code

    =====================================================

    两个优化一起上:

     1 bool v[10002];
     2 deque<int>q;
     3 void spfa(ll s)
     4 {
     5     for(ll i=1;i<=n;i++) d[i]=(ll)(2147483647);
     6     d[s]=0;q.push_back(s);v[s]=1;
     7     sum+=d[s];o++;
     8     while(!q.empty())
     9     {
    10         ll ff=q.front();q.pop_front();v[ff]=0;
    11         sum-=d[ff];o--;
    12         for(ll i=h[ff];i;i=e[i].ne)
    13         {
    14             ll rr=e[i].v;
    15             if(d[rr]>d[ff]+e[i].c)
    16             {
    17                 d[rr]=d[ff]+e[i].c;
    18                 if(!v[rr]) 
    19                 {
    20                     v[rr]=1;
    21                     if(q.empty() || d[rr]>=d[q.front()] || o*d[rr]>=sum) 
    22                      q.push_back(rr);
    23                     else q.push_front(rr);
    24                 }
    25                 
    26             }
    27         }
    28     }
    29 }
    View Code

    至此,完。

    腐草无光,化为萤而跃彩于夏月。

  • 相关阅读:
    @property @synthesize的含义以及误区。
    OC中类的扩展介绍
    Thinking in Java第三、四章学习笔记----操作符与控制执行流程
    LeetCode之Easy篇 ——(12)Integer to Roman
    LeetCode之Easy篇 ——(9)Palindrome Number
    LeetCode之Easy篇 ——(7)Reverse Integer
    LeetCode之Easy篇 ——(1)Two Sum
    Java关键字汇总
    Thinking in Java 第二章学习笔记----一切都是对象
    php文件上传原理详解
  • 原文地址:https://www.cnblogs.com/adelalove/p/8475943.html
Copyright © 2011-2022 走看看