萬圣節的晚上,小Hi和小Ho在吃過晚餐以后,來到了1個巨大的鬼屋!
鬼屋中1共有N個地點,分別編號為1..N,這N個地點之間相互有1些道路連通,兩個地點之間可能有多條道路連通,但是其實不存在1條兩端都是同1個地點的道路。
不過這個鬼屋雖然很大,但是其中的道路其實不算多,所以小Hi還是希望能夠知道從入口到出口的最短距離是多少?
提示:Super Programming Festival Algorithm。每一個測試點(輸入文件)有且唯一1組測試數據。
在1組測試數據中:
第1行動4個整數N、M、S、T,分別表示鬼屋中地點的個數和道路的條數,入口(也是1個地點)的編號,出口(一樣也是1個地點)的編號。
接下來的M行,每行描寫1條道路:其中的第i行動3個整數u_i, v_i, length_i,表明在編號為u_i的地點和編號為v_i的地點之間有1條長度為length_i的道路。
對100%的數據,滿足N<=10^5,M<=10^6, 1 <= length_i <= 10^3, 1 <= S, T <= N, 且S不等于T。
對100%的數據,滿足小Hi和小Ho總是有辦法從入口通過地圖上標注出來的道路到達出口。
對每組測試數據,輸出1個整數Ans,表示那末小Hi和小Ho為了走出鬼屋最少要走的路程。
“唔……地點很多,道路很少,這個鬼屋是1個稀疏圖,既然這1點被特地標注出來,那末想來有其作用的咯?”小Ho道。
“是的,正好有1種最短路徑算法,它的時間復雜度只和邊的條數有關,所以特別合適用來解決這類邊的數量很少的最短路問題!”小Hi點了點頭道:“它就是SPFA算法,即Shortest Path Faster Algorithm?!?/p>
“聽上去很利害的模樣,但是實際上怎樣做的呢?”小Ho問道。
“你會用寬度優先搜索寫這道題么?”小Hi反問道。
“這個固然會啊,構造1個隊列,最開始隊列里只有(S, 0)――表示當前處于點S,從點S到達該點的距離為0,然后每次從隊首取出1個節點(i, L)――表示當前處于點i,從點S到達該點的距離為L,接下來遍歷所有從這個節點動身的邊(i, j, l)――表示i和j之間有1條長度為l的邊,將(j, L+l)加入到隊尾,最后看所有遍歷的(T, X)節點中X的最小值就是答案咯~”小Ho對搜索已是熟稔于心,張口便道。
“SPFA算法呢,其實某種意義上就是寬度優先搜索的優化――如果你在嘗試將(p, q)加入到隊尾的時候,發現隊列中已存在1個(p, q')了,那末你就能夠比較q和q':如果q>=q',那末(p, q)這個節點實際上是沒有繼續搜索下去的必要的――算是1種最優化剪枝吧。而如果q<q',那末(p, q')也是沒有必要繼續搜索下去的――但是它已存在于隊列里了怎樣辦呢?很簡單,將隊列中的(p, q')改成(p, q)就能夠了!”
“那我該怎樣知道隊列中是否是存在1個(p, q')呢?”<額,保護1個position[1..N]的數組就能夠了,如果不在隊列里就是⑴,否則就是所在的位置!”
“所以說這本質上就是寬度優先搜索的剪枝咯?”小Ho問道。
小Hi笑道:“怎樣可能!SPFA算法實際上是BELLMAN-FORD算法的1種優化版本,只不過在成型以后可以被理解成為寬度優先搜索的!這個問題,我們會在以后好好講1講的!”
AC代碼: