私のグラフは平面ですか?


29

あなたの仕事は、グラフが平面かどうかを判断することです。

グラフは、平面に埋め込むことができる場合、つまり交差するエッジなしで描画できる場合は平面です。

入力:次の形式から選択した無向グラフが表示されます。

  • エッジリスト、たとえば [(0, 1), (0, 2), (0, 3)]

  • 隣接マップ、例えば {0: [1, 2, 3], 1:[0], 2:[0], 3:[0]}

  • 隣接行列、例えば [[0, 1, 1, 1], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]

ノード名は数字、文字列などになりますが、選択する形式は任意のグラフをサポートできる必要があります。ノード名にコードを入れません。自己ループはありません。

標準入力、STDIN、コマンドライン引数、関数引数など。

出力:すべての平面グラフに対して特定の出力を返し、すべての非平面グラフに対して異なる特定の出力を返す必要があります。

STDOUT、関数の戻り値など、出力の標準選択。

例:

平面:

[]
[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6)]
[(0,1), (0,2), (0,3), (1,2), (1,3), (2,3)]
[(0,2), (0,3), (0,4), (0,5), (1,2), (1,3), (1,4), (1,5), (2,3),
 (2,5), (3,4), (4,5)]

非平面:

[(0,1), (0,2), (0,3), (0,4), (1,2), (1,3), (1,4), (2,3), (2,4), (3,4)]
[(0,3), (0,4), (0,5), (1,3), (1,4), (1,5), (2,3), (2,4), (2,5)]
[(0,3), (0,4), (0,6), (1,3), (1,4), (1,5), (2,3), (2,4), (2,5), (5,6), 
 (7,8), (8,9), (7,9)]

平面性テストを明示的に実行する関数、または平面埋め込みを明確に参照する関数は許可されません。

これはコードゴルフです。最短のコードが勝つように。


いい質問だね!

これが古典的な問題であり、通常の目的でコードで使用されないものを含むいくつかの可能なアプローチがまだあることは素晴らしいことです。
リルトシアスト

1つの平面コンポーネントと1つの非平面接続コンポーネントを持つ非接続グラフのテストケースが適切です。
ピーターテイラー

@PeterTaylor確かに、1つ追加します。
isaacg

5
@RenaeLider申し訳ありませんが、わかりません。質問は、浮動小数点数とは何の関係もありません-数字さえ使用せず、実際にはラベルだけを使用します。
isaacg

回答:


14

Mathematica、201バイト

f@g_:=EdgeCount@g<9||!(h=g~IsomorphicGraphQ~CompleteGraph@#&)@5&&!h@{3,3}&&And@@(f@EdgeDelete[g,#]&&f@EdgeContract[g,#]&/@EdgeList@g);And@@(f@Subgraph[g,#]&/@ConnectedComponents[g=Graph[#<->#2&@@@#]])&

これは、名前のない関数に評価され、次のようなエッジリストを取ります。

{{0, 3}, {0, 4}, {0, 5}, {1, 3}, {1, 4}, {1, 5}, {2, 3}, {2, 4}, {2, 5}}

これはワーグナーの定理に基づいた恐ろしく非効率的な再帰的アプローチです:

有限グラフは、K 5またはK 3,3をマイナーとして持たない場合にのみ平面です。

ここで、K 5は5つの頂点を持つ完全なグラフであり、K 3,3は各グループに3つの頂点を持つ完全な2部グラフです。グラフAは、一連のエッジ削除とエッジ収縮によってBから取得できる場合、グラフBのマイナーです。

したがって、このコードは、グラフがK 5またはK 3,3と同型かどうかを確認し、そうでない場合は、エッジの削除または縮小の可能性があるたびに再帰的に自身を呼び出します。

キャッチは、接続されていないグラフの1つのコンポーネントでエッジを削除または縮小しても、そこにあるすべての頂点が削除されることはないため、目的の同型が見つからないことです。したがって、入力グラフの各接続コンポーネントに個別にこの検索を適用します。

これは与えられた入力に対して非常に高速に動作しますが、さらにいくつかのエッジを追加すると、破滅的に長くかかります(そして多くのメモリも消費します)。

これは、インデントされたバージョンですf(入力からグラフオブジェクトを生成した後の名前のない関数:

f@g_ := 
  EdgeCount@g < 9 || 
  ! (h = g~IsomorphicGraphQ~CompleteGraph@# &)@5 && 
  ! h@{3, 3} &&
  And @@ (f@EdgeDelete[g, #] && f@EdgeContract[g, #] & /@ EdgeList@g)

そして、これは入力をグラフに変換し、f接続された各コンポーネントを呼び出す名前のない関数です:

And @@ (
  f @ Subgraph[g, #] & /@ ConnectedComponents[
    g=Graph[# <-> #2 & @@@ #]
  ]
)&

終了条件をからEdgeCount@g<9に変更することにより、数バイトを節約できますg==Graph@{}が、ランタイムが大幅に低下します。2番目のテストケースには30秒かかり、最後のテストケースはまだ完了していません。


#0最も内側の純粋な関数を参照する名前付き関数を使用して、削除してみてください。
LegionMammal978

@ LegionMammal978知っていますが、実際には何も保存されません。括弧が必要で#、変数にg手動で割り当てる必要があるためです。
マーティンエンダー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.