CSP认证201609-4交通规划[C++题解]:最短路径树、dijkstra求单源最短路、递推思想
題目分析
來源:acwing
分析: 這題是最短路樹。保持原圖中所有點到根結點的最短距離不變,然后在原圖中選擇一些邊,使所有點連通的最短路是多長。
最短路徑樹,是一種使用最短路徑算法生成的數據結構樹。
定義
考慮一個連通無向圖G,一個以頂點v為根節點的最短路徑樹T是圖G滿足下列條件的生成樹——樹T中從根節點v到其它頂點u的路徑距離,在圖G中是從v到u的最短路徑距離。
來源:維基百科
在這個生成樹上的兩點a和b,如果a能通過b點到達根結點,那么有一個等式d[b]=d[a]+wa?>bd[b] = d[a] + w_{a->b}d[b]=d[a]+wa?>b?,其中d[b]d[b]d[b]和d[a]d[a]d[a]表示該點到根的距離,wa?>bw_{a->b}wa?>b?表示a到b的距離。
既然有了這個等式,其實每個點到根結點的路徑的選項就有限了,因為該點到根的最小距離可以求出來,該點通過其他點到根結點一定滿足上面的等式,所以我們可以預處理出來可行的通路!做法是dijkstra求每個點的最短路,然后遍歷除根之外的所有點,看看它們的鄰邊有哪些是滿足上面這個等式的。
其實,上面等式還說明了另一個問題,就是d[a] 一定比d[b]小,因為邊權都是正的,這就啟發我們將單源最短路的點從小到大排序,從小到大開始查看是否滿足這個等式,滿足的可以和根結點形成樹!
我們假設f(i)表示把前i個點合法掛到根結點所需要的總代價。
在掛第i個點的時候,只有幾個點滿足上述等式(我們稱之為備選邊),
所以有 f(i)=min[f(i?1)+w(被選點→i)]f(i) = min[f(i-1) + w(被選點\rightarrow i)]f(i)=min[f(i?1)+w(被選點→i)]
到這一步,這里公共的是f(i-1),我們只需要求出最小的w(某點->i點)即可。
所以,我們最后求的答案就是不斷從根的鄰點遍歷,求出每個點權值最小的邊(該點需要滿足d[b]=d[a]+wa?>bd[b] = d[a] + w_{a->b}d[b]=d[a]+wa?>b?這個等式)
所以,核心代碼如下
for(int a = 2; a <= n; a ++){int minw = INF; // 遍歷所有的鄰點for(int j = h[a]; ~j; j = ne[j]){int b= e[j];if(dist[a] == dist[b] + w[j])minw = min(minw, w[j]);}res += minw; // 每個點找到權值最小的邊}AC代碼
題目鏈接
總結
以上是生活随笔為你收集整理的CSP认证201609-4交通规划[C++题解]:最短路径树、dijkstra求单源最短路、递推思想的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CSP认证201609-2火车购票[C+
- 下一篇: CSP认证201612-1中间数[C++