色番号を見つける


13

驚いたことに、グラフの色付けに関してはまだ課題がありません!

無向グラフの場合、2つの隣接する頂点が同じ色を共有しないように、各頂点に色を付けることができます。これを達成するために必要な個別の色の最小数χは、有彩色数と呼ばれますは、グラフのます。

たとえば、次の例は、最小数の色を使用した有効な色付けを示しています。

(ウィキペディアで発見)

したがって、このグラフの色数は χ= 3です。

頂点の数N <161から1までの番号が付けられている)が与えられたプログラムまたは関数を書く Nまで)とエッジのリストを指定して、グラフの色数を決定記述します。

入力が前処理されない限り、入力を受け取り、便利なフォーマットで出力を生成できます。つまり、文字列または配列を使用したり、文字列に便利な区切り文字を追加したり、ネストされた配列を使用したりできますが、フラット化された構造には、以下の例と同じ番号が(同じ順序で)含まれている必要があります。

組み込みのグラフ理論関連の関数(MathematicaのようなChromaticNumber)は使用できません。

グラフにループ(頂点とそれ自体を接続するエッジ)がないと仮定できます。これにより、グラフが色付け不能になります。

これはコードゴルフで、最短の回答(バイト単位)が勝ちです。

プログラムは、少なくともこれらすべてを妥当な時間内に解決する必要があります。(すべての入力を正しく解決する必要がありますが、大きな入力の場合は時間がかかる場合があります。)

投稿を短くするために、次の例では、単一のコンマ区切りリストでエッジを示しています。必要に応じて、代わりに改行を使用したり、便利な配列形式の入力を期待したりできます。

三角形(χ= 3)

3
1 2, 2 3, 1 3

6つの頂点の「リング」(χ= 2)

6
1 2, 2 3, 3 4, 4 5, 5 6, 6 1

5つの頂点の「リング」(χ= 3)

5
1 2, 2 3, 3 4, 4 5, 5 1

上の写真例(χ= 3)

6
1 2, 2 3, 3 4, 4 5, 5 6, 6 1, 1 3, 2 4, 3 5, 4 6, 5 1, 6 2

上記の7つの頂点の一般化(χ= 4)

7
1 2, 2 3, 3 4, 4 5, 5 6, 6 7, 7 1, 1 3, 2 4, 3 5, 4 6, 5 7, 6 1, 7 2

ピーターセングラフ(χ= 3)

10
1 2, 2 3, 3 4, 4 5, 5 1, 1 6, 2 7, 3 8, 4 9, 5 10, 6 8, 7 9, 8 10, 9 6, 10 7

5つの頂点の完全なグラフと切断された頂点(χ= 5)

6
1 2, 1 3, 1 4, 1 5, 2 3, 2 4, 2 5, 3 4, 3 5, 4 5

8つの頂点の完全なグラフ(χ= 8)

8
1 2, 1 3, 1 4, 1 5, 1 6, 1 7, 1 8, 2 3, 2 4, 2 5, 2 6, 2 7, 2 8, 3 4, 3 5, 3 6, 3 7, 3 8, 4 5, 4 6, 4 7, 4 8, 5 6, 5 7, 5 8, 6 7, 6 8, 7 8

15頂点の三角形格子(χ= 3)

15
1 2, 1 3, 2 3, 2 4, 2 5, 3 5, 3 6, 4 5, 5 6, 4 7, 4 8, 5 8, 5 9, 6 9, 6 10, 7 8, 8 9, 9 10, 7 11, 7 12, 8 12, 8 13, 9 13, 9 14, 10 14, 10 15, 11 12, 12 13, 13 14, 14 15

合理的に定義できますか?1分?10?
ThreeFx 14

@ThreeFxはい、10分が妥当です。半日ではありません。私は同じ(私の)マシンですべてをもう一度テストする必要があるので、制限を厳しくしたくありません。しかし、マシン上で1時間以内に問題がなければ完了したとしましょう。
マーティンエンダー14

回答:


4

Pythonの2.7 - 122 109 111 109 108 103

f=lambda n,e,m=1:any(all(t*m//m**a%m!=t*m//m**b%m for(a,b)in e)for t in range(m**n))and m or f(n,e,m+1)

使用法:

print f(5, [(1, 2), (2, 3), (3, 4), (4, 5), (5, 1)])

色数(m)を増やすことでブルートフォースを行い、可能なすべての色を確認します。1つの色は、ベースmの数として説明できます。したがって、可能な色は0、1、...、m ^ n-1です。

編集:8頂点の完全なグラフは非常に時間がかかります。しかし、私のラップトップは約10分で解決します。他のテストケースには数秒しかかかりません。


編集2:前処理が許可されていることを読んで、頂点のインデックスを0から始めます。t* m // m ** x%mをt // m ** a%mに短縮します(-2)。ラムダを分解し、mを関数paramsに入れます(-11)


編集3:前処理は許可されません -> t * m(+4)に戻り、//(-2)に簡略化されます。


編集4:任意の(-2)の角括弧を削除します。xnorに感謝します。


編集5:モジュロmを2回取る代わりに、単純にそれらを減算し、その後モジュロ(-1)を使用します。これは、パフォーマンスの大幅な改善でもあります。私のラップトップでは、すべてのテストケースを合わせて約25秒かかります。


編集6:while 1:およびm + = 1(-5)の代わりに再帰呼び出し。もう一度ありがとう、xnor。


いい方法。単純なゴルフ:括弧でall([...])囲む場合a,b(スペースのために文字が不要)、括弧を削除しallて、追加の引数と間違えないようにすることができます。また、mwhileループを使用するのではなく、次に高い関数呼び出しで再帰する場合、charsを保存できると思います。
XNOR

おかげで、再帰的アプローチは+2文字かかります。range for n(n + 1)アプローチのmのAも。
ジャクベ14

私は再帰的なアプローチを少し最適化しanyand/orトリックを使用して、いくつかの文字を保存しますf=lambda n,e,m=1:any(all(t*m//m**a%m!=t*m//m**b%m for(a,b)in e)for t in range(m**n))and m or f(n,e,m+1)
xnor 14

2

Java- 241 218

int k,j,c;int f(int n,int[]e){for(k=1;k<=n;k++)for(long p=0;p<x(n);p++){for(j=0,c=0;j<e.length;c=p%x(e[j])/x(e[j]-1)==p%x(e[j+1])/x(e[j+1]-1)?1:c,j+=2);if(c<1)return k;}return 0;}int x(int a){return(int)Math.pow(k,a);}

制約を考慮してこれを行う最も明白な方法は、ブルートフォースです。各色彩番号をステップスルーkし、各頂点に各色を割り当てます。同じ色の隣人がいない場合は、番号があります。そうでない場合は、一緒に移動します。

これは、次のテストケースに最も時間がかかります。 χ = 8(完全なグラフはここでは問題ありません)が、まだ15秒未満です(OK、最新の編集で約100秒)。

入力は、頂点の数n、およびe[]OPのカンマ区切り値と同じ順序で指定されたエッジ頂点の配列です。

改行あり:

int k,j,c;
int f(int n,int[]e){
    for(k=1;k<=n;k++)
        for(long p=0;p<x(n);p++){
            for(j=0,c=0;
                j<e.length;
                c=p%x(e[j])/x(e[j]-1)==p%x(e[j+1])/x(e[j+1]-1)?1:c,
                j+=2);
            if(c<1)return k;
        }
    return 0;
}
int x(int a){return(int)Math.pow(k,a);}

ああ、これは入力が色付け可能なグラフの一種であると仮定しています。エッジがv1からv1にループする場合、または頂点がない場合、色を付けることはできず、0を出力しますχ=1。エッジのないグラフなどでも機能します。


2

Python 3〜162

同じブルートフォースアプローチを使用しますが、できれば高速に組み合わせを生成するためにitertoolsライブラリを使用します。かなり普通のマシンで、1分未満で完全な8グラフを解きます。

import itertools as I
def c(n,v):
 for i in range(1,n+1):
  for p in I.product(range(i),repeat=n):
   if(0==len([x for x in v if(p[x[0]]==p[x[1]])])):return i

完全な8グラフの場合の使用例:

print(c(8,[x for x in I.combinations(range(8), 2)]))

1

Haskell、163バイト

p x=f(length x)(transpose x)1
f a[b,c]d|or$map(\x->and$g x(h b)(h c))(sequence$replicate a[1..d])=d|0<1=f a b c(d+1)
g a=zipWith(\x y->a!!x/=a!!y)
h=map(flip(-)1)

使用法は次のようになります。

p [[1, 2],[2, 3],[3, 1]]

基本的なブルートフォースアプローチ。有効な場合、すべての可能な色の組み合わせを確認してください。これをさらに短縮するためのヒントを喜んで聞いたことを除いて、ここで言うことはあまりありません;)


頂点のデクリメントと転置は「前処理」としてカウントされます。「便利なフォーマット」で私が念頭に置いたのは、むしろフラットリスト、ネストリスト、文字列、便利なデリミタ付き文字列などから選択できるということでしたが、フラット化された構造はチャレンジで指定されたものと同じである必要があります。
マーティンエンダー14

@MartinBüttnerよし、変更します
ThreeFx 14

@ThreeFxはall id同じであるandany idと同じであるorany id$map f listちょうど同じですany f list。また、あなたはいくつかのことをgすることができます:あなたはそれを次のように再定義することができますg a=(and.).zipWith(\x y->a!!x/=a!!y)する、挿入する、入力する順序を変更する、置換する(\x->g x b c)g b cまたは完全にポイントフリーにしてインラインにすることもできます。これらのいくつかは一緒に動作しないので、それらをすべて試して、最高のものを選択してください:)
誇りに思っているhaskeller 14

1
@MartinBüttnermaaaaanyバイトのコストに固定されていると思います。:D
ThreeFx 14

1
入力に頂点の数がない7番目の例をどのように解きますか?
マーティンエンダー14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.