Treewidth z undirected wykresu jest bardzo ważnym pojęciem w teorii grafów. Wynaleziono mnóstwo algorytmów graficznych, które działają szybko, jeśli masz rozkład wykresu o małej szerokości.
Szerokość grzbietu jest często definiowana w kategoriach rozkładu drzew. Oto wykres i rozkład drzewa tego wykresu, dzięki uprzejmości Wikipedii:
Rozkład drzewa to drzewo, w którym każdy wierzchołek jest powiązany z podzbiorem wierzchołków oryginalnego wykresu, o następujących właściwościach:
- Każdy wierzchołek na oryginalnym wykresie znajduje się w co najmniej jednym z podzbiorów.
- Każda krawędź oryginalnego wykresu ma oba wierzchołki w co najmniej jednym z podzbiorów.
- Wszystkie wierzchołki w rozkładzie, których podzbiory zawierają dany oryginalny wierzchołek, są połączone.
Możesz sprawdzić, czy powyższy rozkład podlega tym regułom. Szerokość rozkładu drzewa jest wielkością jego największego podzbioru minus jeden. Dlatego dla powyższego rozkładu są dwa. Szerokość wykresu jest najmniejszą szerokością rozkładu drzewa tego wykresu.
W tym wyzwaniu otrzymasz połączony, nieukierunkowany wykres i musisz znaleźć jego szerokość.
Chociaż znalezienie rozkładu drzew jest trudne, istnieją inne sposoby obliczania szerokości grzbietu. Strona Wikipedii zawiera więcej informacji, ale jedną z metod obliczania szerokości poprzecznej, o której tam nie wspomniano, która jest często stosowana w algorytmach do obliczania szerokości poprzecznej, jest minimalna szerokość zamówienia eliminacji. Zobacz tutaj artykuł wykorzystujący ten fakt.
W kolejności eliminacji eliminuje się wszystkie wierzchołki wykresu pojedynczo. Po wyeliminowaniu każdego wierzchołka dodawane są krawędzie łączące ze sobą wszystkich sąsiadów tego wierzchołka. Jest to powtarzane, aż wszystkie wierzchołki znikną. Szerokość porządkowania eliminacji jest największą liczbą sąsiadów, jaką ma wyeliminowany wierzchołek podczas tego procesu. Szerokość jest równa minimum we wszystkich rzędach szerokości uporządkowania eliminacji. Oto przykładowy program wykorzystujący ten fakt do obliczenia szerokości poprzecznej:
import itertools
def elimination_width(graph):
max_neighbors = 0
for i in sorted(set(itertools.chain.from_iterable(graph))):
neighbors = set([a for (a, b) in graph if b == i] + [b for (a, b) in graph if a == i])
max_neighbors = max(len(neighbors), max_neighbors)
graph = [edge for edge in graph if i not in edge] + [(a, b) for a in neighbors for b in neighbors if a < b]
return max_neighbors
def treewidth(graph):
vertices = list(set(itertools.chain.from_iterable(graph)))
min_width = len(vertices)
for permutation in itertools.permutations(vertices):
new_graph = [(permutation[vertices.index(a)], permutation[vertices.index(b)]) for (a, b) in graph]
min_width = min(elimination_width(new_graph), min_width)
return min_width
if __name__ == '__main__':
graph = [('a', 'b'), ('a', 'c'), ('b', 'c'), ('b', 'e'), ('b', 'f'), ('b', 'g'),
('c', 'd'), ('c', 'e'), ('d', 'e'), ('e', 'g'), ('e', 'h'), ('f', 'g'), ('g', 'h')]
print(treewidth(graph))
Przykłady:
[(0, 1), (0, 2), (0, 3), (2, 4), (3, 5)]
1
[(0, 1), (0, 2), (1, 2), (1, 4), (1, 5), (1, 6), (2, 3), (2, 4), (3, 4), (4, 6), (4, 7), (5, 6), (6, 7)]
2
[(0, 1), (0, 3), (1, 2), (1, 4), (2, 5), (3, 4), (3, 6), (4, 5), (4, 7), (5, 8), (6, 7), (7, 8)]
3
[(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
4
Otrzymasz wykres jako dane wejściowe i musisz zwrócić szerokość jako wynik. Format wejściowy jest elastyczny. Jako dane wejściowe możesz wziąć listę krawędzi, mapę przylegania lub macierz przylegania. Jeśli chcesz użyć innego formatu wejściowego, zapytaj w komentarzach. Możesz założyć, że wejście jest podłączone i możesz założyć to założenie do swojego formatu wejściowego, np. Używając listy krawędzi.
EDYCJA: Wbudowane operacje obliczające szerokość profilu są niedozwolone. Przepraszam, że nie sprecyzowałem tego z góry.
Najkrótszy kod wygrywa.
źródło
(V,E)
czy byłby to prawidłowy wkład?Odpowiedzi:
Oktawa, 195 bajtów
Funkcja, która przyjmuje jako dane wejściowe macierz przylegania. Zużywa dużą ilość pamięci, więc jest bezużyteczne, jeśli liczba wierzchołków jest większa niż 10-12.
endfunction
jednak dodawać go do tio.Wypróbuj online!
Nie golfowany:
źródło
SageMath,
29 bajtówniekonkurencyjnych ** Ta odpowiedź została zamieszczona przed zmianą OP dotyczącą pytania: „Wbudowane są zbanowane”, więc uczyniłem to niekonkurencyjnym.
Demo online!
źródło
Haskell (Lambdabot),
329321245 bajtówOto moje rozwiązanie, dzięki elastyczności wejścia, które działa na wykresach zawierających wykresy dowolnego typu, który jest instancją
Eq
.Wypróbuj online!
Wersja bez golfa:
źródło