二部ですか?


13

二部グラフは、頂点ないエッジが同じセット内の2つの頂点を接続しないように、2つの互いに素の集合に分割することができるグラフです。グラフが2色である場合にのみ、グラフは2部構成です。


チャレンジ

あなたの仕事は、無向単純グラフの隣接行列を与えられて、それが二部グラフであるかどうかを決定することです。つまり、エッジが頂点iとjを接続する場合、行列の(i、j)と(j、i)の両方のエントリは1です。

グラフは無向で単純なので、その隣接行列は対称であり、0と1のみを含みます。

仕様

入力としてN行N列の行列を使用する必要があります(リストのリスト、文字列のリスト、Cのようなint**サイズ、フラット化された配列、生の入力など、任意の形式で)。

関数/プログラムは、グラフが2部構成である場合は真偽値を返し、そうでない場合は偽である必要があります。

テストケース

['00101',
 '00010',
 '10001',
 '01000',
 '10100'] : False
['010100',
 '100011',
 '000100',
 '101000',
 '010000',
 '010000'] : True (divide into {0, 2, 4, 5} and {1, 3})
['00',
 '00'] : True

得点

答えを直接計算する組み込み関数は禁止されています。

これはなので、今月末までに最短のプログラム(バイト単位)が勝ちます!


関連し、実際にはボーダーラインのだまされやすい。なぜなら、二部であることは奇数サイクルを持たないことに相当し、その質問に対する答えのほとんどは、すべてのサイクルを列挙し、その長さを調べることによって機能するからである。
ピーターテイラー

@PeterTaylorうん、しかし、この問題を解決する簡単な方法があります。
コレラSu

@ColeraSu真実/偽りの代わりに、偽りの-1場合と真実の場合に負でない整数を返すことができますか?
ミスターXcoder

@MishaLavrov- 0> Falsy、>0-> Truthyは通常、標準の真実/偽のルールで許可されています。-1そして、≥ 0私は尋ねた理由です、それは一般的ではありません。
ミスターXcoder

@ Mr.Xcoder大丈夫です。
コレラSu

回答:


4

、17バイト

§V¤=ṁΣṠMSȯDfm¬ṀfΠ

グラフが2部グラフである場合、正の整数を出力します0オンラインでお試しください!

説明

これは総当たり的なアプローチです。頂点のすべてのサブセットSを反復処理し、グラフ内のすべてのエッジがSとその補数の間にあるかどうかを確認します。

§V¤=ṁΣṠMSȯDfm¬ṀfΠ  Implicit input: binary matrix M.
                Π  Cartesian product; result is X.
                   Elements of X are binary lists representing subsets of vertices.
                   If M contains an all-0 row, the corresponding vertex is never chosen,
                   but it is irrelevant anyway, since it has no neighbors.
                   All-1 rows do not occur, as the graph is simple.
      ṠM           For each list S in X:
              Ṁf   Filter each row of M by S, keeping the bits at the truthy indices of S,
        S  fm¬     then filter the result by the element-wise negation of S,
         ȯD        and concatenate the resulting matrix to itself.
                   Now we have, for each subset S, a matrix containing the edges
                   from S to its complement, twice.
§V                 1-based index of the first matrix
  ¤=               that equals M
    ṁΣ             by the sum of all rows, i.e. total number of 1s.
                   Implicitly print.

@ Mr.Xcoderさて、M = [[1,2,3],[4,5,6],[7,8,9]]and S = [1,0,1]Mプログラムでは常にバイナリ行列ですが、この方法で説明する方が簡単です)と仮定します。各列フィルタリングMによってはS得られる[[1,3],[4,6],[7,9]]:行ごとに、私はそれらのインデックスで要素を削除S0そしてIネゲート有するS要素単位得るために[0,1,0]、フィルタMを取得することにより、[[4,6]]第1及び最後の行は、対応するインデックス0を有します、したがって削除されます。
Zgarb

17

Wolfram言語(Mathematica)26 25バイト

Tr[#//.x_:>#.#.Clip@x]<1&

オンラインでお試しください!

使い方

隣接行列Aが与えられた場合、B = Aで始まり、その後BをA 2 Bで置き換える不動点を見つけます。1から1より大きい値をクリッピングすることがあります。このプロセスのk 番目のステップは、Clip検出力までです。+ 1 2K(i、j)のエントリは、jにI頂点から長2K + 1のパスの数をカウントします; したがって、固定小数点は、奇数のステップでiからjに移動できる場合に限り、ゼロ以外の(i、j)エントリを持つことになります。

特に、固定点の対角線は、頂点が奇数のステップで奇数のサイクルがある場合にのみ頂点に到達できる場合にのみ、ゼロ以外のエントリを持ちます。そのため、固定点のトレースは、グラフが2部からなる場合にのみ0です。

この形式の別の25バイトソリューションはTr[#O@n//.x_:>#.#.x]===0&、バイトカウントをさらに低くする方法についてだれかにアイデアを提供できる場合に備えて、です。

これまでの取り組み

私はこの答えに落ち着く前に、この答えにいくつかのアプローチを試みました。

26バイト:行列指数

N@Tr[#.MatrixExp[#.#]]==0&

また、隣接行列の奇数乗に依存します。X * EXPので(X 2)X + xは3 + X 5 /2!+ X 7 /4] + ...、xが行​​列Aの場合、これはAの奇数乗ごとに正の項を持つため、Aが奇数サイクルの場合はトレースもゼロになります。このソリューションは、大きな行列の場合は非常に遅くなります。

29バイト:奇数の大きな力

Tr[#.##&@@#~Table~Tr[2#!]]<1&

n行n列のマトリックスAの場合、A 2n + 1を見つけて、対角チェックを行います。ここ#~Table~Tr[2#!]で、n行n列の入力行列の2n個のコピーを生成し、に#.##& @@ {a,b,c,d}アンパックしa.a.b.c.dて、結果として行列の2n + 1個のコピーを乗算します。

53バイト:ラプラシアン行列

(e=Eigenvalues)[(d=DiagonalMatrix[Tr/@#])+#]==e[d-#]&

スペクトルグラフ理論のあいまいな結果を使用します(このPDFの命題1.3.10)。


を使用すると、より効率的な方法で数バイト削ることができると思いますTr[#.Nest[#.#&,#,Tr[#!]]]<1&。(これは私がそれを見るたびに良くなり続ける信じられないほどの答えです!)
樹ではありません

1
これには、セミビルトインよりもバイト数が少ない(2つの関数が必要)BipartiteGraphQ@AdjacencyGraph@#&
ケリーロウダー

2
@KellyLowder:大きな行列のMatrixExp場合、評価さRootれていないオブジェクトに関して結果が返されますが、追加時に自動的に単純化されません。N@軍これらRootsがtruthinessはその後、評価できるようにすることを数値的に計算されます。
マイケルサイフェルト

1
@Notatreeあなたのアプローチは確かに数バイトを削減しますが、コストがかかります。18x18マトリックスの場合、1000倍遅くなり、そこから悪化します。その変更を行うと、効率的なメソッドを「効率的」と呼ぶ権利を失います。
ミシャラヴロフ

1
@KellyLowderこれはに短縮できますがBipartiteGraphQ@*AdjacencyGraph、それでも長くなります。
マーティンエンダー

3

JavaScript、78バイト

m=>!m.some((l,i)=>m.some((_,s)=>(l=m.map(t=>t.some((c,o)=>c&&l[o])))[i]&&s%2))

0/1の配列の入力配列、true / falseを出力します。


2

Pyth、25バイト

xmyss.D.DRx0dQx1d.nM*FQss

オンラインでお試しください!

これは-1、偽の場合に返され、偽の場合は負でない整数を返します。

使い方

xmyss.D.DRx0dQx1d.nM * FQss〜完全なプログラム。STDINから隣接行列を受け取ります。

                    * FQ〜デカルト積による削減(折り畳み)。
                 .nM〜それぞれをフラット化します。
 m〜変数dを持つマップ。
         RQ〜入力の各要素に対して、
       .D〜インデックスの要素を削除...
          x0d〜dの0のすべてのインデックス。
     .D〜このリストから、インデックスの要素を削除します...
              x1d〜dの1のすべてのインデックス。
    s〜平坦化。
   s〜合計。[]が表示されない場合は、sを使用できます。
  y〜ダブル。
x〜上記のマッピングで、最初のインデックスを取得...
                       ss〜入力行列の1の総数。

これは、現在のPythバージョンTiOが持っているコミットd315e19で機能します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.