第一階段複習

Vegdie發表於2024-05-05

目錄
  • 最短路部分
    • 最小環
    • 傳遞閉包
    • 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),與假設矛盾。命題得證。

來自OI-Wiki

反圖

負環

例題:拉近距離

image

image

最短路計數

方法:因為不涉及權值,所以單純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就一定不成立。
  • 好在該題可以一條邊重複走。

分層圖的幾個典例

最短路結合二分

例題:通往奧格瑞瑪的道路

邊權是扣的血量。點權是要花的路費。

那肯定是最短路和邊權有關。

二分最小花費,每次跑一次最短路。

單調性:如果

相關文章