Jest to problem z kolorowaniem wykresów .
Przypomnij sobie, że kolorowanie wykresu to przypisanie koloru do wierzchołków wykresu w taki sposób, że żadne dwa wierzchołki, które dzielą krawędź, również nie będą miały tego samego koloru. W szczególności (abstrakcyjne) wierzchołki wykresu to wielokąty. Dwa wierzchołki są połączone (niekierowaną) krawędzią, gdy przecinają się (jako wielokąty). Jeśli weźmiemy jakieś rozwiązanie problemu - który jest sekwencją (powiedzmy k ) rozłącznych kolekcji wielokątów - i przypiszemy unikalny kolor do każdej kolekcji w sekwencji, uzyskamy k -kolorowanie wykresu . Pożądane jest znalezienie małego k .
Ten problem jest dość trudny i pozostaje nierozwiązany w przypadku dowolnych grafów. Rozważ przybliżone rozwiązanie, które można łatwo kodować. Algorytm sekwencyjny powinien zrobić. Algorytm Welsha-Powella jest chciwym rozwiązaniem opartym na malejącej kolejności wierzchołków według stopnia. Przetłumaczone na język oryginalnych wielokątów, najpierw posortuj wielokąty w porządku malejącym względem liczby innych wielokątów, które się na siebie nakładają. Pracując w porządku, nadaj pierwszemu wielokątowi początkowy kolor. Na każdym kolejnym kroku spróbuj pokolorować następny wielokąt istniejącym kolorem: wybierz kolor, który nie jestużywany już przez któregokolwiek z sąsiadów tego wielokąta. (Istnieje wiele sposobów wyboru spośród dostępnych kolorów; wypróbuj ten, który był najmniej używany, lub wybierz jeden losowo.) Jeśli następnego wielokąta nie można pokolorować istniejącym kolorem, utwórz nowy kolor i pokoloruj go tym.
Po uzyskaniu kolorowania za pomocą niewielkiej liczby kolorów wykonaj statystyki strefowe kolor po kolorze: z uwagi na konstrukcję masz pewność, że żadne dwa wielokąty danego koloru nie zachodzą na siebie.
Oto przykładowy kod w R
. (Kod w Pythonie nie różni się zbytnio.) Po pierwsze, opisujemy nakładanie się siedmiu pokazanych wielokątów.
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)
Oznacza to, że wielokąty 1 i 2 nakładają się, podobnie jak wielokąty 2 i 3, 3 i 4, ..., 1 i 7.
Sortuj wierzchołki według malejącego stopnia:
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))]
(Surowy) algorytm sekwencyjnego kolorowania używa najwcześniejszego dostępnego koloru, który nie jest jeszcze używany przez nakładający się wielokąt:
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
}
Zainicjuj struktury danych ( colors
i color.next
) i zastosuj algorytm:
colors <- rep(0, length(vertices))
color.next <- 1
temp <- sapply(v, color)
Podziel wielokąty na grupy według kolorów:
split(vertices, colors)
Dane wyjściowe w tym przykładzie wykorzystują cztery kolory:
$`1`
[1] 2 4
$`2`
[1] 3 6 7
$`3`
[1] 5
$`4`
[1] 1
Podzielił wielokąty na cztery niezachodzące na siebie grupy. W tym przypadku rozwiązanie nie jest optymalne ({{3,6,5}, {2,4}, {1,7}} to trójkolorowy wykres). Ogólnie rzecz biorąc, rozwiązanie, które dostaje, nie powinno być jednak takie złe.