首先先明確乙個問題,spfa是什麼?(不會看什麼看,一邊學去,傳送門),spfa是bellman-ford的佇列優化版本,只有在國內才流行spfa這個名字,大多數人就只知道spfa就是乙個頂尖的高效演算法,卻不知道還能繼續優化,這個優化雖然也沒有你想的那麼麻煩,只不過多了幾個判斷語句罷了,5分鐘就能學會,但是這也得運用到分類討論,其實spfa有三種優化方法,效果並不是很明顯。
這三個測試點通過情況所對應的分別是spfa的三種優化方法,這個時間也是因題而異,像這道題,效果並不好,但是看別人寫的部落格,他們提交了一道資料對於優化後的spfa比較有利,測試時間差距能看出來,但是效果也就是減少十幾毫秒而已,但是也是有的,萬一題目會卡這十幾毫秒呢?
1.
slf優化
還記得嗎?在我們學spfa的時候,要把每乙個入隊的點插入到隊尾,可是有些時候這個點作為隊尾沒有作為隊頭效率高,因為這個點有時放在隊首就能直接用,那麼什麼樣的點作為隊首更好呢?當然是dis值越小越可能重新整理其它dis值,所以對比當前元素與對首元素的dis值,如果當前元素的dis值更小,那麼把當前元素插入到隊首,否則插入到隊尾。如果你不是很了解佇列,或者還是現學的,一定會納悶,不就能q.push( );嗎?哪來的隊首呢?此時queueq;應該改為dequeq;雙端佇列,就有q.push_front( );和q.push_back( );了。
**如下(紅色處為優化對應的新增**):
12. lll優化如果懂了上乙個slf優化,那麼這個lll優化就很好理解了,slf表示小的優先,lll表示大的最後,那麼什麼樣的的dis值是大的呢?難道還和隊首元素比較嗎?當然不是,是於佇列的平均數來比較,如果大於這個平均數就放到最後。void
spfa()221
}22}23
}24 }
**如下(紅色處為優化對應的新增**):
12. slf+lll優化這個就很簡單直接了,把兩個新增**搓一塊了就行。void
spfa()214
sum-=dis[p];cnt_2--;
15 vis[p]=0;16
for(int i=head[p];i;i=map[i].next)
1729}30
}31}32 }
**如下(紅色處為優化對應的新增**):
1怎麼樣,你學會了嗎?void
spfa()214
sum-=dis[p];cnt_2--;
15 vis[p]=0
;;16
for(int i=head[p];i;i=map[i].next)
1730}31
}32}33 }
最短路徑演算法 SPFA
求最短路徑的演算法有許多種,除了排序外,恐怕是oi界中解決同一類問題演算法最多的了。最熟悉的無疑是dijkstra,接著是bellman ford,它們都可以求出由乙個源點向其他各點的最短路徑 如果我們想要求出每一對頂點之間的最短路徑的話,還可以用floyd warshall。spfa是這篇日誌要寫...
SPFA演算法 最短路徑
只要最短路徑存在,spfa演算法必定能求出最小值,spfa對bellman ford演算法優化的關鍵之處在於意識到 只有那些在前一遍鬆弛中改變了距離估計值的點,才可能引起他們的鄰接點的距離估計值的改變。為什麼隊列為空就不改變了呢?就是因為要到下一點必須經過它的前乙個鄰接點。spfa可以處理負權邊。很...
SPFA演算法 最短路徑
spfa是一種求單源最短路的演算法 演算法中需要用到的主要變數 int n 表示n個點,從1到n標號 int s,t s為源點,t為終點 int d n d i 表示源點s到點i的最短路 int p n 記錄路徑 或者說記錄前驅 queue q 乙個佇列,用stl實現,當然可有手打佇列,無所謂 bo...