Удивительно, но у нас еще не было проблем с раскраской графиков!
Учитывая неориентированный граф, мы можем дать каждой вершине такой цвет, чтобы никакие две смежные вершины не имели одинаковый цвет. Наименьшее число χ различных цветов, необходимое для достижения этого, называется хроматическим числом графа.
Например, ниже показано допустимое окрашивание с использованием минимального количества цветов:
(Найдено в Википедии)
Таким образом, хроматическое число этого графа χ = 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
источник
Ответы:
Python 2.7 -
122109111109108103Использование:
Грубая сила путем увеличения хроматического числа (м) и проверьте все возможные окраски. Одна раскраска может быть описана как число в базе m. Таким образом, возможные окраски 0, 1, ..., m ^ n-1.
редактировать: полный граф из 8 вершин занимает довольно много времени. Но мой ноутбук решает это за 10 минут. Другие тестовые случаи занимают всего несколько секунд.
правка 2: прочитайте, что предварительная обработка разрешена, поэтому я позволяю индексу вершин начинаться с 0: сокращает t * m // m ** x% m до t // m ** a% m (-2). Растворите лямбду и введите m в функциональные параметры (-11)
редактировать 3: предварительная обработка не разрешена -> обратно к t * m (+4), упрощено // до / (-2).
редактировать 4: удалить квадратные скобки в любом (-2), спасибо xnor.
редактировать 5: вместо того, чтобы взять по модулю m дважды, просто вычтите их и затем используйте по модулю (-1). Это тоже значительное улучшение производительности. Все тесты вместе занимают около 25 секунд на моем ноутбуке.
edit 6: рекурсивный вызов вместо while 1: и m + = 1 (-5). Еще раз спасибо, xnor.
источник
all([...])
если заключите скобки в скобкиa,b
(которые не стоят здесь символов из-за пробелов), чтобы ониall
не принимали их за дополнительные аргументы. Кроме того, я подозреваю, что вы можете сохранить символы, если вы выполняете процедуру с вызовом функции до следующего наивысшего уровня,m
а не с помощью цикла while.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)
.Ява -
241218Наиболее очевидный способ сделать это с учетом ограничений - это грубая сила. Просто пройдитесь по каждому хроматическому числу
k
и назначьте каждый цвет каждой вершине. Если нет соседей одного цвета, у вас есть ваш номер. Если нет, двигайтесь вперед.Это длится дольше всего для тестового примера
χ = 8
(полные графики здесь отстой), но это все еще меньше 15 секунд (хорошо, около 100 с последним редактированием).Входные данные - это число вершин
n
и массив вершин ребер,e[]
заданных в том же порядке, что и значения OP, разделенные запятыми.С переносами строк:
О, и это предполагает, что вход является своего рода графом раскрашивания. Если ребро переходит от v1 к v1 или нет вершин, оно не может быть окрашено и будет выводить 0. Оно все равно будет работать для графиков без ребер
χ=1
и т. Д.источник
Питон 3 - 162
Использует тот же подход грубой силы, но использует библиотеку itertools для, как мы надеемся, более быстрой генерации комбинации. Решает полный 8-граф за <1 мин на моей довольно обычной машине.
Пример использования для полного 8-графового случая:
источник
Haskell, 163 байта
Использование было бы так:
Основной подход грубой силы. Проверьте все возможные цветовые комбинации, если они действительны. Больше нечего сказать, кроме того, что я рад услышать любые советы по сокращению этого еще дальше;)
источник
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
или даже сделать его полностью Точки бесплатно и коридорным его. некоторые из них не работают вместе, поэтому попробуйте их все и выберите лучший :)