Informatyczny kącik olimpijski
Świąteczny łańcuch
Tym razem omówimy zadanie Świąteczny łańcuch, które rozwiązywali w tym roku uczestnicy drugiego etapu XXIII Olimpiady Informatycznej.
Zadanie jest następujące:
Zadanie. Należy zaprojektować łańcuch złożony z różnokolorowych lampek, przy czym dane jest również wymagań estetycznych, każde w postaci trójki liczb oznaczającej, że fragmenty łańcucha złożone z lampek o numerach oraz muszą być jednakowe (Rys. 1). Łańcuch powinien być też jak najbardziej urozmaicony; innymi słowy, powinno być w nim jak najwięcej różnych kolorów lampek. Wartości i są rzędu
Rozwiązanie, za które można było zdobyć połowę punktów na konkursie, jest narzucające się. Zbudujmy graf o wierzchołkach (ponumerowanych liczbami od 1 do ), które odpowiadać będą kolejnym lampkom łańcucha. Teraz dla każdego wymagania estetycznego łączymy krawędziami wierzchołki dla tych lampek, które muszą mieć ten sam kolor; innymi słowy, dla każdego łączymy krawędzią wierzchołki oraz Zauważmy, że wszystkie lampki należące do jednej spójnej składowej grafu muszą mieć ten sam kolor. Z kolei lampki z różnych składowych mogą mieć różne kolory, więc aby zmaksymalizować liczbę kolorów w łańcuchu, należy każdej składowej przypisać inny kolor lampek (Rys. 2). To rozwiązanie działać będzie w czasie liniowym od wielkości skonstruowanego grafu. Jest zatem zbyt wolne, gdyż liczba krawędzi grafu może być bliska iloczynowi który może wynieść nawet
Zauważmy, że powyższe rozwiązanie jest wolne, jeśli istnieje dużo wymagań estetycznych o dużych długościach (wartościach ). Jednak w takim przypadku jest nieuniknione, że spora część wymagań będzie redundantna (tzn. będzie prowadziła do takich samych wymuszeń kolorów). W naszym przykładzie wymaganie mówi, że fragmenty i mają takie same kolory lampek, co może być spełnione tylko wtedy, gdy krótsze fragmenty oraz mają te same kolory. Widać zatem, że wymaganie jest w tym przypadku zawsze spełnione. Chcielibyśmy usunąć takie redundantne wymagania. Ponadto, w przypadku wymagań o dużych długościach być może tylko część informacji z wymagania jest redundantna - w takim przypadku dobrym pomysłem mogłoby być podzielenie takiego wymagania na mniejsze kawałki.
W szybszym rozwiązaniu wykorzystamy te dwa pomysły: będziemy sukcesywnie rozbijać wymagania na mniejsze i na bieżąco usuwać redundancje. Rozwiązanie będzie przebiegać w fazach dla W fazie -tej zakładamy, że wszystkie wymagania mają długość co najwyżej a następnie każde wymaganie o długości większej niż (czyli spełniającej ) zastępujemy dwoma wymaganiami o długości (Rys. 3):
To spowoduje tymczasowy wzrost liczby wymagań, ale pozwoli nam usunąć redundancje wśród wymagań o długości Zbudujmy w tym celu graf w którym wierzchołki będą znów liczbami od 1 do ale będziemy mieli co najwyżej krawędzi: dla każdego wymagania stworzymy krawędź łączącą wierzchołki oraz Zauważmy teraz, że jeśli w grafie znajduje się cykl, to znaczy, że część wymagań o długości daje redundantne informacje. Istotnie: cykl wymusza, że dla każdego kolory lampek ze zbioru są takie same. Jednak to samo wymuszenie uzyskujemy, jeśli usuniemy dowolne wymaganie odpowiadające krawędzi z tego cyklu. Powtarzając to rozumowanie dopóty, dopóki w grafie istnieją cykle, możemy zmniejszyć zbiór wymagań długości do zbioru liczącego wymagań. Ten zbiór możemy znaleźć, wyznaczając dowolny las rozpinający grafu
Zatem na koniec fazy -tej uzyskamy równoważny zbiór wymagań zawierający co najwyżej wymagań długości co najwyżej Pojedynczą fazę możemy zaimplementować w czasie Tak więc po fazie uzyskamy równoważny zbiór wymagań, z których każde jest długości 1. Dla takiego zbioru nasze pierwotne rozwiązanie zadziała w czasie liniowym. Ostatecznie złożoność czasowa algorytmu wyniesie a pamięciowa