評測題:洛谷【模板】單源最短路徑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 }
==================================================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 }
==================================================================================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 }
=====================================================
兩個優化一塊兒上:


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 }
至此,完。
腐草無光,化爲螢而躍彩於夏月。