Istnieje standardowy algorytm znajdowania najdłuższej ścieżki w nieukierunkowanych drzewach przy użyciu dwóch wyszukiwań w pierwszej kolejności:
- Uruchom DFS od losowego wierzchołka i znajdź od niego najdalszy wierzchołek; powiedzmy, że to v ′ .
- Teraz uruchom DFS od aby znaleźć wierzchołek najdalej od niego. Ta ścieżka jest najdłuższą ścieżką na wykresie.
Pytanie brzmi, czy można to zrobić bardziej efektywnie? Czy możemy to zrobić za pomocą pojedynczego DFS lub BFS?
(Można to równoznacznie opisać jako problem obliczania średnicy drzewa bezkierunkowego).
algorithms
graphs
trees
Emmy
źródło
źródło
Odpowiedzi:
Po drodze przeprowadzamy wyszukiwanie w pierwszej kolejności i agregujemy wyniki, tzn. Rozwiązujemy problem rekurencyjnie.
Dla każdego węzła z dziećmi u 1 , … , u k (w drzewie wyszukiwania) istnieją dwa przypadki:v u1, … , Uk
W drugim przypadku musimy połączyć jedną lub dwie najdłuższe ścieżki od do jednego z poddrzewa; są to z pewnością te do najgłębszych liści. Długość ścieżki wynosi zatem H ( k ) + H ( k - 1 ) + 2, jeśli k > 1 lub H ( k ) + 1, jeśli k = 1 , przy H = { h ( T u i ) ∣ i = 1 , …v H.( k )+ H( k - 1 )+ 2 k > 1 H.( k )+ 1 k = 1 zbiór wielu wysokości poddrzewa¹.H.= { h ( Tuja) ∣ i = 1 , … , k }
W pseudokodzie algorytm wygląda następująco:
źródło
height1 + height2
jest długość tej ścieżki. Jeśli jest to rzeczywiście najdłuższa ścieżka, wybiera jąmax
. Wyjaśniono to również w powyższym tekście, więc nie bardzo widzę twój problem? Na pewno musisz się powtórzyć, aby dowiedzieć się, czy rzeczywiście jest to najdłuższa ścieżka, a nawet jeśli nie, nie zaszkodzi (wrt poprawności) powtórzyć.height2
jawnie usuwa sięheight1
z rozważań, więc jak może wybrać to samo dziecko dwa razy? Zostało to również wyjaśnione w tekście wprowadzającym.longestPathHeight(T)
zwraca parę(h,d)
, w którejh
wysokośćT
id
średnica toT
. (Zgadza się?)Można to rozwiązać w lepszy sposób. Możemy również zmniejszyć złożoność czasu do O (n), wprowadzając niewielką modyfikację struktury danych i stosując podejście iteracyjne. Dla szczegółowej analizy i wielu sposobów rozwiązania tego problemu z różnymi strukturami danych.
Oto podsumowanie tego, co chcę wyjaśnić w moim blogu :
Podejście rekurencyjne - średnica drzewa Inny sposób podejścia do tego problemu jest następujący. Jak wspomniano powyżej, średnica może
Co oznacza, że średnicę można idealnie wyprowadzić
Wiemy, że średnica jest najdłuższą ścieżką, dlatego bierzemy maksymalnie 1 i 2 w przypadku, gdy leży ona z boku lub weźmy 3, jeśli obejmuje ona rdzeń.
Podejście iteracyjne - średnica drzewa
Mamy drzewo, potrzebujemy meta informacji z każdym węzłem, aby każdy węzeł wiedział, co następuje:
Gdy każdy węzeł uzyska te informacje, potrzebujemy zmiennej tymczasowej, aby śledzić maksymalną ścieżkę. Do czasu zakończenia algorytmu mamy wartość średnicy w zmiennej temp.
Teraz musimy rozwiązać ten problem w podejściu oddolnym, ponieważ nie mamy pojęcia o trzech wartościach dla katalogu głównego. Ale znamy te wartości dla liści.
Kroki do rozwiązania
W danym węźle
źródło
Poniżej znajduje się kod, który zwraca ścieżkę średnicy przy użyciu tylko jednego przejścia DFS. Wymaga dodatkowej przestrzeni, aby śledzić najlepszą dotychczas widoczną średnicę, a także najdłuższą ścieżkę rozpoczynającą się od określonego węzła w drzewie. Jest to podejście do programowania dynamicznego oparte na tym, że najdłuższa ścieżka średnicy albo nie zawiera korzenia, albo jest kombinacją dwóch najdłuższych ścieżek sąsiadów korzenia. Potrzebujemy zatem dwóch wektorów do śledzenia tych informacji.
źródło