切換
舊版
前往
大廳
主題

ZeroJudge - e792: a3.旅行(Trip) 解題心得

Not In My Back Yard | 2020-06-08 01:25:16 | 巴幣 4 | 人氣 297

題目連結:


題目大意:
第一列給定三正整數 N 、 M 、 Q (2 ≦ N ≦ 200 , 1 ≦ M≦ N × (N - 1) , 1 ≦ Q ≦ 20000),代表有 N 個國家(編號為 0 ~ N - 1)、 M 個航班 、 Q 筆詢問。

接著有 M 列,每列給定兩非負整數 X 、 Y ,代表存在一個直達航班為國家 X 到國家 Y(注意這是單向的,並非雙向)。

再接著有 Q 列,每列給定兩非負整數 A 、 B ,試問可否從國家 A 搭航班到國家 B (可由多個航班間接地抵達)。可以的話,輸出「YES」;反之,輸出「NO」。



範例輸入:
範例輸入一:
3 2 2
0 1
1 2
0 2
1 0

範例輸入二:
5 4 5
4 3
0 3
3 1
1 2
4 3
3 2
3 0
1 0
3 4


範例輸出:
範例輸出一:
YES
NO

範例輸出二:
YES
YES
NO
NO
NO


解題思維:
這題可以使用 Floyd-Warshall 演算法解決。其演算法基本架構如下:
foreach temp in nodes
  foreach i in nodes
    foreach j in nodes
      d[i][j] = min(d[i][j], d[i][k] + d[k][j])
其中,nodes 即代表圖的節點(在本題為各個國家),d[i][j] 代表從 i 到 j 的最短距離。

一開始對於所有的 i 、 j 值,d[i][j] 設為無限大(理論上要這樣,但在程式裡就初始化一個很大的數字即可,除非距離值非常地大)。而對於每條邊 E(i, j) ,d[i][j] 就設定為該條邊的距離(或是成本等等)。

而該演算法的精神就是:
對於每個節點對 (i, j) ,窮舉第三個節點 k 作為中繼。如果從 i 到 k 再從 k 到 j ,會比原本的 d[i][j] 的距離短,則 d[i][j] 就更新成前者的值。因為如果中繼節點 k 是 i 到 j 的路徑上的其中一個中間節點,則代表無論現在的路徑如何,現在走去 k 一定較短。反之,走去 k 一定較遠。

可以看到這個演算法可以應付有正向環或有向邊的圖之最短路徑(如果存在負環,則這個演算法會失效)。而且支援全對數(All-pair)詢問,意即跑完一次演算法之後,所有節點對 (i, j) 的最短距離都會一併知道(只要不更改邊的距離(成本、權重))。



而本題只需要問國家 A 可不可以到國家 B ,所以邊的距離完全不重要。可以將距離全部設為 0 ,然後看最後 d[A][B] 是不是 0 就知道 A 可不可以到 B 。而使用此演算法的好處就是,可以不用每問一對 A 、 B 就要跑一次最短距離演算法。

此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。

創作回應

更多創作