Це проблема фарбування графіків .
Нагадаємо, що забарвлення графа - це призначення кольору вершинам графа таким чином, що жодна дві вершини, які ділять ребро, також не матимуть однакового кольору. Зокрема, (абстрактні) вершини графа є багатокутниками. Дві вершини з'єднуються з (непрямим) ребром, коли вони перетинаються (як багатокутники). Якщо ми візьмемо будь-яке рішення проблеми - яка є послідовністю (скажімо, k ) роз'єднаних колекцій багатокутників - і присвоїмо унікальний колір кожній колекції в послідовності, то ми отримаємо k -кольорування графіка . Бажано знайти невелику k .
Ця проблема досить складна і залишається невирішеною для довільних графіків. Розглянемо приблизне рішення, яке просто кодувати. Послідовний алгоритм повинен зробити. Алгоритм Уельша-Пауелла - це жадібне рішення, засноване на низхідному впорядкуванні вершин за ступенем. Перекладені мовою оригінальних багатокутників, спочатку сортуйте багатокутники у порядку зменшення кількості інших багатокутників, які вони перетинаються. Працюючи в порядку, надайте першому багатокутнику початковий колір. На кожному наступному етапі намагайтеся пофарбувати наступний багатокутник наявним кольором: тобто виберіть колір, який не євже використовується будь-яким із сусідів цього полігону. (Існує багато способів вибрати серед доступних кольорів; спробуйте або найменш використаний, або виберіть один випадковим чином.) Якщо наступний багатокутник не можна пофарбувати наявним кольором, створіть новий колір і пофарбуйте його цим.
Після того як ви домоглися забарвлення з невеликою кількістю кольорів, виконайте зональнестатування кольором за кольором: за конструкцією ви гарантуєте, що жоден два полігони заданого кольору не перекриваються.
Ось зразок коду в R
. (Код Python не дуже сильно відрізняється.) Спочатку ми описуємо перекриття серед семи показаних багатокутників.
edges <- matrix(c(1,2, 2,3, 3,4, 4,5, 5,1, 2,6, 4,6, 4,7, 5,7, 1,7), ncol=2, byrow=TRUE)
Тобто багатокутники 1 і 2 перекриваються, і так само багатокутники 2 і 3, 3 і 4, ..., 1 і 7.
Сортуйте вершини за низхідним ступенем:
vertices <- unique(as.vector(edges))
neighbors <- function(i) union(edges[edges[, 1]==i,2], edges[edges[, 2]==i,1])
nbrhoods <- sapply(vertices, neighbors)
degrees <- sapply(nbrhoods, length)
v <- vertices[rev(order(degrees))]
Алгоритм (неочищеного) послідовного забарвлення використовує найраніший доступний колір, який вже не використовується жодним полігоном, що перекривається:
color <- function(i) {
n <- neighbors(i)
candidate <- min(setdiff(1:color.next, colors[n]))
if (candidate==color.next) color.next <<- color.next+1
colors[i] <<- candidate
}
Ініціалізуйте структури даних ( colors
і color.next
) та застосуйте алгоритм:
colors <- rep(0, length(vertices))
color.next <- 1
temp <- sapply(v, color)
Розділіть багатокутники на групи за кольором:
split(vertices, colors)
Вихід у цьому прикладі використовує чотири кольори:
$`1`
[1] 2 4
$`2`
[1] 3 6 7
$`3`
[1] 5
$`4`
[1] 1
Він розділив багатокутники на чотири групи, що не перекриваються. У цьому випадку рішення не є оптимальним ({{3,6,5}, {2,4}, {1,7}} є триколірним для цього графіка). Загалом, рішення, яке воно отримує, не повинно бути занадто поганим.