SPFA的兩個優化

評測題:洛谷【模板】單源最短路徑ide

不加任何優化:優化

 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

==================================================url

優化1(SLF:Small Label First):spa

使用雙端隊列(詳見代碼註釋).net

證實:顯然定理 code

 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

==================================================================================blog

優化2(LLL:Large Label Last):隊列

使用雙端隊列,sum爲隊列中因此元素的dis和,o爲隊列中元素個數get

即x=sum/o;io

對於當前點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

至此,完。

腐草無光,化爲螢而躍彩於夏月。

相關文章
相關標籤/搜索