關於SPFA的優化


SPFA兩個著名優化(SLF和LLL):

SPFA 是按照 FIFO 的原則更新距離的, 沒有考慮到距離標號的作用。

實現中 SPFA 有兩個非常著名的優化: SLF 和 LLL。

 

SLF: Small Label First 策略. (比較常用)
實現方法:設隊首元素為 i, 隊列中要加入節點 j, 在 d_j \le d_i 時加到隊首而不是隊尾, 否則和普通的 SPFA 一樣加到隊尾. 

 

LLL: Large Label Last 策略. (不太常用)

設隊列 Q 中的隊首元素為 i,距離標號的平均值為 $\overline d = \frac {\sum_{j \in Q} d_j }{\left| Q \right|}$,每次出隊時,若 $d_i > \overline d$,把 移到隊列末尾,如此反復,直到找到一個 $i$ 使 $d_i \le \overline d$,將其出隊。 

話說某次在群里問過關於SLF優化的實現問題,木人理我。。。           。

網上這方面的資料貌似也不多。。。。

這兩天看到了雙端隊列,然后就突然想起了SLF優化。。自己實現了下,大牛請無視。

以POJ 3259為例,上面的是優化后的,下面的是不加優化的。不加優化的SPFA 跑了157MS,加了SLF優化后跑了94MS。可以看出,使用SLF優化可以節約一部分的時間。

 

 

SLF代碼實現(POJ 3259):

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <cstdio>
  5 #include <deque>
  6  using  namespace std;
  7  const  int N= 501;
  8  const  int NN= 100001;
  9  const  int inf= 0x7fffffff;
 10  int n,nu;
 11 typedef  struct node
 12 {
 13      int adj,val;
 14      struct node *next;
 15 };
 16 node node[NN],*p[N];
 17  int SPFA()
 18 {
 19     deque< int> qu;
 20      int x,i,a,b;
 21      int vis[N],dis[N],num[N];
 22      struct node *head[N];
 23      for(i= 1;i<=n;i++)
 24     {
 25         vis[i]= 0;
 26         num[i]= 0;
 27         dis[i]=inf;
 28         head[i]=p[i];
 29     }
 30     dis[ 1]= 0;
 31     vis[ 1]= 1;
 32     num[ 1]++;
 33     qu.push_back( 1);
 34      while(!qu.empty())
 35     {
 36         x=qu.front();
 37         qu.pop_front();
 38         vis[x]= 0;
 39         head[x]=p[x];
 40          while(head[x])
 41         {
 42             a=head[x]->adj;
 43             b=head[x]->val;
 44              if(dis[a]>dis[x]+b)
 45             {
 46                 dis[a]=dis[x]+b;
 47                  if(!vis[a])
 48                 {
 49                     vis[a]= 1;
 50                     num[a]++;
 51                      if(num[a]>=n)
 52                          return  1;
 53                      if(!qu.empty())
 54                     {
 55                          if(dis[a]>dis[qu.front()])
 56                             qu.push_back(a);
 57                          else
 58                             qu.push_front(a);
 59                     }
 60                      else
 61                         qu.push_back(a);
 62                 }
 63             }
 64             head[x]=head[x]->next;
 65         }
 66     }
 67      return  0;
 68 }
 69  int main()
 70 {
 71      int t,i,m,w,a,b,c;
 72     scanf( " %d ",&t);
 73      while(t--)
 74     {
 75         memset(node, 0, sizeof(node));
 76         memset(p, 0, sizeof(p));
 77         nu= 0;
 78         scanf( " %d%d%d ",&n,&m,&w);
 79          for(i= 0;i<m;i++)
 80         {
 81             scanf( " %d%d%d ",&a,&b,&c);
 82             node[nu].adj=b;
 83             node[nu].val=c;
 84             node[nu].next=p[a];
 85             p[a]=&node[nu];
 86             nu++;
 87             node[nu].adj=a;
 88             node[nu].val=c;
 89             node[nu].next=p[b];
 90             p[b]=&node[nu];
 91             nu++;
 92         }
 93          for(i= 0;i<w;i++)
 94         {
 95             scanf( " %d%d%d ",&a,&b,&c);
 96             node[nu].adj=b;
 97             node[nu].val=-c;
 98             node[nu].next=p[a];
 99             p[a]=&node[nu];
100             nu++;
101         }
102          if(SPFA())
103             puts( " YES ");
104          else
105             puts( " NO ");
106     }
107      return  0;
108 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM