最短路徑 SPFA演算法優化

2022-07-12 11:18:09 字數 1491 閱讀 1208

首先先明確乙個問題,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( );了。

**如下(紅色處為優化對應的新增**):

1

void

spfa()221

}22}23

}24 }

2. lll優化如果懂了上乙個slf優化,那麼這個lll優化就很好理解了,slf表示小的優先,lll表示大的最後,那麼什麼樣的的dis值是大的呢?難道還和隊首元素比較嗎?當然不是,是於佇列的平均數來比較,如果大於這個平均數就放到最後。

**如下(紅色處為優化對應的新增**):

1

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 }

2. slf+lll優化這個就很簡單直接了,把兩個新增**搓一塊了就行。

**如下(紅色處為優化對應的新增**):

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...