目錄
- 最短路部分
- 最小環
- 傳遞閉包
- Dij證明
- 反圖
- 負環
- 最短路計數
- 次短路
- 分層圖的幾個典例
- 最短路結合二分
最短路部分
最小環
一些細節:列舉最小環是依據還沒有更新經過k的最短路,所以要寫在更新經過k的最短路之前。要判斷是否存在路徑。ijk三指標需要i與k、j與k相連。
傳遞閉包
f[i][j] |= f[i][k] & f[k][j];
注意是有向圖
Dij證明
命題:在取出最短路長度最小的節點u的時候,u的最短路已經被確定,即D(u)=dis(u)
證明:設u是演算法中第一個在加入S集合時不滿足D(u)=dis(u)的點。(u的存在性略)。一定存在一條路徑s→x−y→u,其中y是路徑上第一個屬於T集合的點。而x和y直接相連,顯然x∈S。
因為D(x)=dis(x),所以(x,y)會被鬆弛,於是加入u的時候,一定有,D(y)=dis(y)
因為邊權為正,所以D(y)≤D(u),從而dis(y)≤D(y)≤D(u)≤dis(u)。但因為u被取出,所以dis(u)≤dis(y),故D(u)=dis(u),與假設矛盾。命題得證。
反圖
負環
例題:拉近距離
最短路計數
方法:因為不涉及權值,所以單純bfs就好。自環不會影響結果,因為如果經過自環,一定比不經過自環要長,所以輸入判自環。重邊會影響結果,但是一樣計入即可(可不可以用乘法什麼的最佳化)。在遇到一個沒訪問過的點時,一定是最短路,更新即可,該點的計數+=前驅的計數;若遇到訪問過的點,且該點最短路長度大於前驅最短路長度(其實這兩個長度必定只差1),則依然更新,其他情況都不是最短路,不更新。這題做完了。
次短路
例題:[USACO06NOV]Roadblocks G
- 首先想到在最短路演算法的過程中計算次短路。進而想到開兩個陣列,一個是dis1用來存最短路,一個是dis2用來存次短路。
- 更新最/次短路是最重要的一點。
- 對於u向v的更新:(定義折線長度為u點最短路加(u,v)邊權)
- 判斷1:如果dis1[v]可以更新,則更新dis1[v] 。(這裡可以加一句,讓dis2[v]等於先前的dis1[v] )
- 判斷2:如果dis1[v]不能更新(這不代表dis2[v]不能更新)。那麼如果折線長度小於dis2[v],而且折線長度大於dis1[v](這個dis1[v]並沒有被更新,注意這裡的邏輯),則更新dis2[v]為折線長度。
- 判斷3:注意到判斷2中更新dis2[v]的是最短路的折線長度,這一定比次短路的折線長度更優,所以判斷2若不成立,那麼才考慮,用次短路的折線長度更新。換個角度理解,這個演算法其實是兩次鬆弛,判斷2保證了嚴格小於最短路的次短路。
- 對於三個判斷,有一個成立,就要入隊。因為更新勢必造成對之後的影響,就要入隊。而且從if,else if的角度也很好理解。
- 這裡可以發現,判斷123是轉折的,可以用else-if連線,比方說,判斷2成立,判斷3就一定不成立。
- 好在該題可以一條邊重複走。
分層圖的幾個典例
最短路結合二分
例題:通往奧格瑞瑪的道路
邊權是扣的血量。點權是要花的路費。
那肯定是最短路和邊權有關。
二分最小花費,每次跑一次最短路。
單調性:如果