Знайдіть хроматичне число


13

Дивно, але ми не мали жодних проблем з розфарбуванням графіків!

Давши непрямий графік, ми можемо надати кожній вершині такий колір, щоб жодна дві сусідні вершини не мали однакового кольору. Найменше число χ різних кольорів, необхідних для досягнення цього, називається хроматичним числом графіка.

Наприклад, нижче показано дійсне забарвлення з використанням мінімальної кількості кольорів:

(Знайдено у Вікіпедії)

Отже, хроматичне число цього графа дорівнює χ = 3 .

Напишіть програму або функцію, яка за кількістю вершин N <16 (які пронумеровані від 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

@ThreeFx так, 10 хвилин розумно. півдня не. Я не хочу бути занадто суворим на межі, тому що мені потрібно ще раз перевірити все на тій же (моїй) машині. але скажімо, якщо це завершиться протягом години на вашій машині, це добре.
Мартін Ендер

Відповіді:


4

Пітон 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. Тож можливі забарвлення 0, 1, ..., m ^ n-1.

редагувати: Повна графа з 8 вершин займає досить багато часу. Але мій ноутбук вирішує це приблизно за 10 хвилин. Інші тестові випадки займають лише кілька секунд.


редагувати 2: Прочитайте, що попередня обробка дозволена, тому я дозволяю індексу вершин починати з 0: скорочує t * m // m ** x% m до t // m ** a% m (-2). Розведіть лямбда і введіть m у параметри функцій (-11)


правити 3: попередня обробка НЕ допускається -> назад до т * м (+4), спрощена // к / (-2).


редагувати 4: видалити квадратні дужки в будь-якому (-2), завдяки xnor.


редагуйте 5: замість того, щоб взяти модуль м двічі, просто відніміть їх і потім використовуйте модуль (-1). Це також досить поліпшення продуктивності. Всі тести разом займають близько 25 секунд на моєму ноутбуці.


редагувати 6: рекурсивний виклик замість 1: і m + = 1 (-5). Ще раз дякую, xnor.


Хороший метод. Простий гольф: Ви можете зняти дужки, all([...])якщо вкладете a,bв парен (що тут не вимагає знаків через пробіл), щоб allне помилитися з ними для додаткових аргументів. Крім того, я підозрюю, що ви можете зберегти символи, якщо повторити виклик функції до наступного найвищого, mа не використовувати цикл час.
xnor

Дякую, рекурсивний підхід займає + 2 символи. Підхід A для m у діапазоні (n + 1).
Якубе

Я оптимізував Рекурсивний підхід трохи з anyі and/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

2

Ява - 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 секунд (добре, близько 100s з останнім редагуванням).

Вхід - це кількість вершин 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

Пітон 3 - 162

Використовує той же підхід, який застосовується з грубою силою, але використовує бібліотеку itertools для сподівання швидшого створення комбінацій. Вирішує повний 8-графік за <1 хв на моїй досить звичайній машині.

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]]

Основний підхід грубої сили. Перевірте всі можливі комбінації кольорів, якщо вони дійсні. Тут не багато чого сказати, крім того, що я радий почути будь-які поради щодо скорочення цього ще більше;)


Я б сказав, що декрементація вершин і їх перенесення вважається "попередньою обробкою". Що я мав на увазі під "будь-яким зручним форматом", це було скоріше, що ви можете вибрати з плоского списку, вкладеного списку, рядка, рядка зі зручними роздільниками тощо.
Мартін Ендер

@ MartinBüttner Добре, я його
поміняю

@ThreeFx all id- те саме and, що any idє orі any 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

1
@ MartinBüttner Я думаю, що це виправлено до вартості байаані байт. : D
ThreeFx

1
Як ви вирішуєте 7-й приклад без кількості вершин у введенні?
Мартін Ендер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.