プリム法で全部の倉庫を道でつなぐいちばん安い費用を求める

グラフ問題 116

平面に散らばった倉庫を、碁盤の目の道でつないで、どの 2 つも行き来できるようにするいちばん安い費用を求めます。つないだまとまりから最も近い倉庫を 1 つずつ足していく、最小全域木のプリム法の練習です。

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

問題

碁盤の目の町に、倉庫が散らばっています。倉庫の場所を、点 [x, y] の並び points で受け取ります。2 つの倉庫 [x1, y1] と [x2, y2] を道で結ぶ費用は、碁盤の目に沿った距離 |x1 - x2| + |y1 - y2| です。

何本かの道を作って、どの 2 つの倉庫のあいだも (ほかの倉庫を通ってもよいので) 行き来できるようにします。かかる費用の合計のいちばん安い値を返す関数を書いてください。

  • 道は、倉庫と倉庫を直接結ぶ物だけを作れます
  • points の長さは 1 以上 1000 以下、x と y はどれも -1000000 以上 1000000 以下の整数で、同じ場所の倉庫はありません
  • 倉庫が 1 つなら、道は要らないので 0 を返します

入力と出力の例

例 1

[0, 0] と [1, 3] を 4、[0, 0] と [4, 1] を 5、[4, 1] と [5, 5] を 5 で結ぶと、合計 14 で全部がつながります。

points = [[0, 0], [1, 3], [4, 1], [5, 5]]
14

例 2

一列に並んだ倉庫は、隣どうしを結ぶのがいちばん安く、3 + 2 + 4 で 9 です。

points = [[0, 0], [3, 0], [5, 0], [9, 0]]
9

例 3

倉庫が 1 つです。

points = [[-7, 2]]
0

面接での聞かれ方

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

  • 「平面の点を全部つなぐ最小の費用を返してください。2 点の費用はマンハッタン距離です」
  • 書き終えると「クラスカル法とプリム法のどちらを選びましたか? この問題ではなぜそちらですか?」と聞かれます
  • 「全部の点の組が辺になるとき、辺の数はいくつですか?」と、辺の多いグラフでの計算量を聞かれます

道が直接結ぶ物だけか、点の数がどれくらいかを最初に確かめておくと、どの書き方が間に合うかが決まります。

ヒント

まだ開いていません

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

  1. ヒント 2

  2. ヒント 3

  3. ヒント 4答えに近い

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

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

main.py
def min_cost_connect(points: list[list[int]]) -> int:
    """
    Goal: 何を返すか

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

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

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


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

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