ダイクストラ法で合図が全部の中継所に届くまでの時間を求める

一方通行の回線でつながった中継所に、1 か所から合図を流したとき、全部の中継所に届くまでの時間を求めます。重みのある最短経路を、ヒープで近い所から確定していくダイクストラ法で解く練習です。

海外で定番の問題リスト 4 本には入っていません

問題

山あいに n か所の無線の中継所があり、1 から n の番号が付いています。回線の並び links を受け取ります。links[i] = [a, b, t] は、中継所 a から中継所 b へ合図を送る一方通行の回線で、届くのに t 秒かかります。

中継所 src から合図を流します。合図を受けた中継所は、すぐに出ている全部の回線へ合図を送り直します。全部の中継所に合図が届くまでの秒数を返す関数を書いてください。届かない中継所があるなら -1 を返します。

  • それぞれの中継所に届く時刻は、届き方のうちいちばん早い時刻です。全部に届くまでの秒数は、その中のいちばん遅い時刻です
  • n は 1 以上 100 以下、links の長さは 0 以上 6000 以下、t は 0 以上 100 以下の整数です
  • 同じ a から同じ b への回線は 2 本ありません。自分へ戻る回線もありません

入力と出力の例

例 1

1 から 2 へ直接は 5 秒ですが、1、3、2 と回ると 1 + 2 で 3 秒です。4 へは 3 から 4 秒で、1 + 4 の 5 秒です。いちばん遅い 4 の 5 秒を返します。

links = [[1, 2, 5], [1, 3, 1], [3, 2, 2], [3, 4, 4]] n = 4 src = 1
5

例 2

回線は 2 から 1 への一方通行だけです。1 から流した合図は 2 へ届きません。

links = [[2, 1, 3]] n = 2 src = 1
-1

例 3

中継所は 1 か所で、回線がありません。流した所にもう届いています。

links = [] n = 1 src = 1
0

面接での聞かれ方

面接では、短く次のように渡されることが多いです。

  • 「重み付きの有向グラフで、ある節から全部の節へ信号が届くまでの時間を返してください。届かない節があれば -1 です」
  • 幅優先探索 (BFS) で書くと「辺の重さが違うとき、BFS の順で正しいですか?」と聞かれます
  • 「重さが負の辺があったら、ダイクストラ法は使えますか?」と広げて聞かれることがあります

回線が一方通行か、重さが 0 や負になるかを最初に確かめておくと、ダイクストラ法を使ってよいかが決まります。

ヒント

まだ開いていません

付箋は 4 枚。下の段ほど答えに近づきます

  1. ヒント 2

  2. ヒント 3

  3. ヒント 4答えに近い

アルゴリズムのチートシートの「グラフ探索と幅優先探索」に、この型の要点を表とコードでまとめています。

グラフ探索は、つながりを近い順か奥からたどります。迷路、最短の手数、講座を受ける順のような問題が同じ形です。

main.py
def network_delay(links: list[list[int]], n: int, src: int) -> int:
    """
    Goal: 何を返すか

    idea1: まず思いつく案
    -> runtime: O(?)  space: O(?)

    idea2: もっと速い案
    -> runtime: O(?)  space: O(?)

    edge case: 空、1 つだけ、など
    """
    # ここに書きます
    pass


# 「実行」を押すと、この行の結果が出ます
print(network_delay([[1, 2, 5], [1, 3, 1], [3, 2, 2], [3, 4, 4]], 4, 1))

できているか「例で確かめる」を押すと、問題の例を全部この関数に渡して、通ったかをここに出します