Мій графік планарний?


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

Будь-яка функція, яка явно виконує тестування на планарність або іншим чином конкретно посилається на планарні вбудовування, заборонена.

Це код гольфу. Нехай найкоротший код виграє.


Приємне запитання!

Чудово, що це класична проблема, і все ще існує кілька можливих підходів, в тому числі, які не використовуються в коді для звичайних цілей.
lirtosiast

Тестовий випадок для непідключеного графіка з одним планарним та одним непланарним з’єднаним компонентом було б добре.
Пітер Тейлор

@PeterTaylor Звичайно, я додам його.
isaacg

5
@RenaeLider Вибачте, але я не розумію. Питання не має нічого спільного з числами з плаваючою комою - він навіть не використовує цифри, а лише мітки.
isaacg

Відповіді:


14

Математика, 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 вершинами в кожній групі. Графік A є другорядним графіком B, якщо його можна отримати з B шляхом послідовності видалення ребер та реберних скорочень.

Таким чином, цей код просто перевіряє, чи графік є ізоморфним до K 5 або K 3,3, а якщо ні, то він рекурсивно викликає себе один раз для кожного можливого видалення або стиснення краю.

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

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

Ось з відступною версією 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@{}, але це значно підірве час виконання. Потім другий тестовий випадок займає 30 секунд, а останній ще не завершений.


Ви можете спробувати видалити названу функцію, використовуючи, #0яка відноситься до найпотужнішої чистої функції.
LegionMammal978

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