Informatyczny kącik olimpijski
Zalesianie
Tym razem omówimy zadanie Zalesianie, które pojawiło się na finale zawodów drużynowych XII Olimpiady Informatycznej Gimnazjalistów.
Zadanie (Zalesianie). Danych jest wierzchołków ponumerowanych od
do
Ciąg
składa się z wartości przyporządkowanych kolejnym wierzchołkom (
to wartość przyporządkowana
-temu wierzchołkowi). Naszym zadaniem jest zbudować drzewo (spójny, acykliczny graf), przez ustalenie
krawędzi między wierzchołkami oraz wybranie wierzchołka, który będzie korzeniem. Chcemy to zrobić w taki sposób, aby zminimalizować współczynnik niezadowolenia. Współczynnik niezadowolenia to maksymalna wartość wyrażenia
dla takich
i
że
jest przodkiem
(
oznacza operację bitową xor).

Zastanówmy się najpierw nad strukturą drzewa, które budujemy. Zauważmy, że korzeń jest przodkiem każdego innego wierzchołka w tym drzewie. Zatem, licząc współczynnik niezadowolenia, zawsze będziemy rozpatrywali każdą taką parę wierzchołków i
że
jest korzeniem drzewa. Okazuje się, że istnieje drzewo, w którym nie ma więcej par wierzchołków pozostających w relacji przodek-potomek. Wystarczy wybrać korzeń oraz połączyć go krawędziami ze wszystkimi pozostałymi wierzchołkami. Obok schemat takiego drzewa
oznacza korzeń).
Ustaliliśmy już strukturę drzewa. Opiszemy teraz, w jaki sposób wybrać taki korzeń, który będzie minimalizował współczynnik niezadowolenia.
Rozwiązanie
Pierwszy, najbardziej intuicyjny pomysł, polega na naiwnym sprawdzeniu każdego z sposobów ustalenia korzenia. Dla każdego wierzchołka
konstruujemy drzewo, którego korzeniem jest
oraz pozostałe wierzchołki są z nim połączone krawędzią. Następnie, dla każdego z tych drzew obliczamy (z definicji) współczynnik niezadowolenia. Spośród otrzymanych wyników wybieramy najmniejszy. Drzew mamy
(po jednym dla każdego kandydata na korzeń). Obliczenie współczynnika niezadowolenia dla jednego drzewa odbywa się w czasie
Zatem cały algorytm działa w czasie
Rozwiązanie
Potraktujmy zapisy binarne elementów ciągu jako słowa nad alfabetem
Niech
oznacza zapisy binarne kolejnych elementów ciągu
(
oznacza zapis binarny
który nie zawiera zer wiodących). Następnie "wyrównajmy" długości słów ciągu
Chcemy otrzymać słowa o takiej samej długości, równej długości najdłuższego słowa w ciągu
W tym celu wszystkie krótsze słowa należy poprzedzić odpowiednią liczbą zer wiodących. Kolejno otrzymane słowa nazwijmy
Podobnie jak w rozwiązaniu dla każdego potencjalnego korzenia chcemy obliczyć współczynnik niezadowolenia. W istocie, dla każdego
chcemy znaleźć takie
że
jest maksymalne. Na potrzeby tego artykułu zakładamy, że każdemu
jest przypisana wartość
oraz
ma wartość
Weźmy dla którego szukamy takiego
że
jest maksymalne. Idealnie byłoby, gdyby istniało
(
oznacza negację
). Wtedy
czyli najlepszy możliwy wynik. Ta obserwacja daje nam pewną intuicję. Będziemy wyszukiwali
cyfra po cyfrze, w kolejności od najbardziej znaczących do najmniej znaczących. Załóżmy, że mamy już ustalony prefiks
słowa
Zastanawiamy się teraz, jaką wartość może mieć
Oczywiście, gdyby
wtedy wynik wzrósłby o
Zatem, jeśli
jest prefiksem jakiegoś słowa w ciągu
to
w przeciwnym przypadku
Prosty dowód pozostawiamy Czytelnikowi.
Pozostało nam jeszcze opisać, w jaki sposób dla danego słowa sprawdzać, czy jest ono prefiksem jakiegoś słowa w ciągu W tym celu zbudujemy drzewo trie nad słowami ciągu
Wyszukiwanie
cyfra po cyfrze odpowiada wędrówce w drzewie trie od korzenia do liści. Załóżmy, że w danym kroku ustalamy wartość
Jeśli wierzchołek, w którym jesteśmy, ma dwóch synów, to poruszamy się krawędzią z etykietą
W przeciwnym przypadku nie mamy wyboru - idziemy krawędzią z etykietą
Wędrówkę kończymy w liściu. Kolejno wybierane etykiety krawędzi tworzą szukane

Konstrukcja drzewa trie zajmuje czas Wyznaczenie
dla danego
zajmuje czas
(długość ścieżki od korzenia do liścia). Współczynnik niezadowolenia obliczamy dla każdego z
potencjalnych drzew, co w sumie daje
operacji. Zatem cały algorytm działa w czasie
Rozważmy przykład. Niech Wówczas
a drzewo trie widać na rysunku obok.