最短路徑

圖的最短路徑

只是個人的總結, 防止忘記

定義: 找到一個點到另一個頂點成本最小的路徑

Dijkstra( 權重非負, 有無環都可)

能夠得到最短路徑的算法, 只要證明自己可以放松所有的邊, 直到都失效為止.

對于樸素算法: 需要最終所有節點都被放松過

對于有限隊列優化的: 優先級最小的頂點的distTo[]值就是最短路徑的權重, 它不會小于任意已經放松過的任意頂點的最短路徑的權重, 也不會大于任何還未被放松過的任意頂點的最短路徑的權重. 這樣, 所有s可以到達的頂點的最短路徑都按照最短路徑的權重順序被放松.

如果沒有環, 那可以用拓撲排序優化, 先拓撲排序, 然后按照順序放松節點, 這是無環最優化的, 且可以處理負權重邊.

可以做的leetcode題目

(https://leetcode-cn.com/problems/path-with-maximum-probability/)

(https://leetcode-cn.com/problems/path-with-minimum-effort/)

(https://leetcode-cn.com/problems/network-delay-time/)

Dijkstra像是 BFS 和 PRIM 算法.

樸素的Dijkstra:

會放松所有的邊, ans里的節點都會被訪問到. 且可以看到一個節點的距離值可以被多次修改.

 // 3. dijkstra
  def dijkstraSolution(times: Array[Array[Int]], n:Int, k:Int): Int = {
    import scala.collection.mutable
    val tu = mutable.Map[Int, mutable.Map[Int, Int]]()
    (1 to n).foreach{ i => tu.put(i, mutable.Map[Int, Int]())}
    times.foreach{
      case Array(uid, vid, weight) => {
        tu(uid).put(vid, weight)
      }
    }
    val ans = mutable.Map[Int, Int]((1 to n).map( _ -> Integer.MAX_VALUE):_*) // 這個, ans的元素綜合為n個和88行, 保證了全部能被訪問到
    ans.update(k, 0)

    val visitedSet = mutable.Set[Int]()
    while(visitedSet.size != n) {
      val _@(miniNode, miniWeight): (Int, Int) = ans.filterNot(e => visitedSet.contains(e._1)).minBy(_._2)
      visitedSet.add(miniNode)
        //   println("visited: " + visitedSet.map(_.toString))
        //   println("ans" + ans.toMap)
      val adjs: mutable.Map[Int, Int] = tu(miniNode)
      adjs.foreach{
        case (adjNode, adjValue) => {
          ans(adjNode) =  math.min(adjValue + miniWeight,  ans(adjNode))
        //   ans.update(adjNode, math.min(adjValue + miniWeight,  ans(adjNode)))
        }

      }
    }

    if(ans.values.exists( _ == Integer.MAX_VALUE)) {
      -1
    }else{
      ans.values.max
    }

  }

優先隊列優化的

在設置一個點的距離前, 會將所有之前放松其他邊得到的可能最小距離值, 放到優先隊列中.

另外, 優先隊列里的元素, 是修改它的值, 還是重新壓入,使得隊列中存在失效的數據. 這兩種方式, 前者是即時實現, 后者是lazy的延時實現.(我沒太明白算法4里的這個)

  // 4. optimized dijstra
  def optimized_dijstra(times: Array[Array[Int]], n: Int, k: Int) = {
    import scala.collection.mutable
    val tu = mutable.Map[Int, mutable.Map[Int, Int]]()
    (1 to n).foreach{ i => tu.put(i, mutable.Map[Int, Int]())}
    times.foreach{
      case Array(uid, vid, weight) => {
        tu(uid).put(vid, weight)
      }
    }
    val ans = mutable.Map[Int, Int]((1 to n).map( _ -> Integer.MAX_VALUE):_*)
    implicit val tupleOrdering: Ordering[(Int, Int)] = new Ordering[(Int, Int)]{
      override def compare(x: (Int, Int), y: (Int, Int)): Int = x._1 - x._2
    }
    val updateSignalPriorityQueue = mutable.PriorityQueue[(Int, Int)]()(tupleOrdering)
    updateSignalPriorityQueue.enqueue((k,0))
      
    while(updateSignalPriorityQueue.nonEmpty) { // method1

      val _@(miniNode, updatedWeight) = updateSignalPriorityQueue.dequeue()

      // 如果沒有被更新過...
      // 被更新過
      if(ans(miniNode) == Integer.MAX_VALUE || updatedWeight < ans(miniNode)) { 
    //  if( ans(miniNode) == Integer.MAX_VALUE || !visitedSet.contains(miniNode)) {
        ans(miniNode) = updatedWeight
        // visitedSet.add(miniNode)
        tu(miniNode).foreach {
          case _@(adjV, adjW) => {
            updateSignalPriorityQueue.enqueue(adjV -> (updatedWeight + adjW))  // 這個方法的復雜度和對有限隊列的操作成正比, updateWeight < ans(miniNOde)保證了失效的邊不會再作用, 但也是個彈出操作, 而如果在
                                                                              // 這里, 不用enqueue, 如果adjV存在于有限隊列,修改它的值,并且,調整順序, 總調整次數與彈出操作次數相同
          }
        }
      }else{
            ()
      }
    }
    if(ans.values.exists( _ == Integer.MAX_VALUE)) {
      -1
    }else{
      ans.values.max
    }
  }

確定無環的用拓撲排序優化

bfs 或者 dfs 的方式

效率不高 , 可以忽略

變種

最長路徑
  1. 轉換視角, 非負權重圖的最短路徑就是 負權重值的最長路徑 , 只要把原圖的權重全部取反, 最后得到結果后再取反就好.
  2. 改變relax函數中的不等式方向, 原來是新的權重如果小于舊的權重更新, 現在改成, 新的權重如果大于舊的則更新

兩種方法都是轉化了視角, 最短和最長是一對對偶.

另外, 在加權有向圖(權重可能為負數) 中尋找最長路徑, 已知最好的算法的復雜度也是指數級別的, 而若是有環, 則更復雜了.

并行任務調度

優先級限制下的并行任務調度定義:

  1. 一組需要完成的任務和每個任務所需時間
  2. 一組關于任務完成的先后次序的優先級限制

在滿足此限制條件下, 在數量不限的處理器上安排這些任務, 使得任務最快完成, 且使用的處理器資源最少(可以理解為cpu不要忙等, 即給定任務要直接執行, 而不是還要再等它的前序先完成)最少.

這個問題, 可以通過"關鍵路徑"的方法證明它和 "無環加權有向圖"的最長路徑 問題等價

將定義里的兩個條件轉換成對應的圖:

image.png
image.png

將任務轉化成圖的一條邊, 邊有兩個點, 任務的時間就是邊的權重, 而 "關鍵路徑" 即條件二: 優先級次序 轉化而來的, 關鍵路徑之間轉化的節點間也有路徑, 不過權重為0 , 此外, 開始S具有0權重到任意任務的開始節點, 任意任務的結束節點有0權重到結束節點. 第二章圖中的最長路徑, 就是每個路徑的開始節點的最長路徑權重值就是它的任務開始時間.

相對最后期限下的并行任務調度

和上個情況不同的是, 多了一個限制類型: 某個任務需要在指定的時間點之前開始, 即指定和另一個任務的開始時間的相對時間. 舉例: 任務2 必須在任務4 開始后的12個時間內啟動.

等價為; 加權有向圖(可能環以及負權重邊)的最短路徑問題

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,963評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,348評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,083評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,706評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,442評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,802評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,795評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,983評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,542評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,287評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,486評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,030評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,710評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,116評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,412評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,224評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,462評論 2 378

推薦閱讀更多精彩內容