Informatyczny kącik olimpijski
Zagadka
W tym kąciku przyjrzymy się zadaniu Zagadka, które pojawiło się na tegorocznych Potyczkach Algorytmicznych.
Przede wszystkim zauważmy, że powyższe wymagania ograniczające
możliwości wyboru stolic możemy zamienić na zestaw zdań logicznych.
Dla każdego miasta
wprowadźmy zmienną logiczną
oznaczającą, czy dane miasto jest stolicą swojego województwa. Wówczas drogę
łączącą miasta
i
możemy rozumieć jako alternatywę
. Województwo interpretujemy natomiast jako zbiór alternatyw
postaci
dla każdej pary różnych miast
,
z tego województwa.
W ten sposób sprowadziliśmy zadanie do wybrania dla każdego miasta
wartości zmiennej logicznej
, tak aby zachodziły wszystkie wymienione
wyżej alternatywy. (Jeżeli znajdziemy rozwiązanie, w którym pewne
województwo nie ma żadnej stolicy, to w takim przypadku możemy
dowolne jego miasto uznać za jego stolicę i nie zepsuje to znalezionego
rozwiązania.) Jest to klasyczny problem 2-SAT, dla którego znany jest liniowy
(dokładniej: liniowo zależny od liczby zmiennych i liczby alternatyw)
algorytm. W przypadku naszego zadania oznacza to rozwiązanie w czasie
. Nie jest to jeszcze wynik satysfakcjonujący. Aby go poprawić,
zagłębimy się w działanie algorytmu rozwiązującego problem 2-SAT, po czym
spróbujemy go przyspieszyć dla tego konkretnego zadania.
Zauważmy, że każdą alternatywę
możemy zamienić na dwie
implikacje:
oraz
. Zbudujemy zatem graf, którego
wierzchołkami są
oraz
dla wszystkich
,
a krawędziami – implikacje powstałe ze wszystkich naszych alternatyw.
Chcemy dla każdego miasta
wybrać dokładnie jeden z dwóch
odpowiadających mu wierzchołków i uznać za prawdziwy, pamiętając przy
tym o implikacjach. Nietrudno spostrzec, że w każdej silnie spójnej
składowej takiego grafu wszystkie wierzchołki mają taką samą wartość
logiczną. Jeśli utożsamimy wierzchołki należące do tych samych silnie
spójnych składowych, otrzymujemy tzw. graf silnie spójnych składowych,
w którym nie ma już cykli. Ten graf sortujemy topologicznie. Rozpatrujemy
kolejno te silnie spójne składowe, z których wychodzą krawędzie tylko do już
rozpatrzonych. Zauważmy, że jeśli
i
są w tej samej
silnie spójnej składowej, to
i
także, gdyż jeśli
z
można dojść krawędziami do
, to z
można
analogicznie dojść do
, podobnie jeśli można dojść
z
do
, to można z
do
(wynika to ze
sposobu konstrukcji krawędzi z alternatyw). W takim razie, podczas
rozpatrywania kolejnych składowych, jeśli napotykamy taką, której
komplementarna nie została jeszcze rozpatrzona, ustalamy, że wszystkie
wierzchołki tej składowej będą prawdziwe, a komplementarnej – fałszywe.
W ten sposób dla każdej pary literałów
,
zdecydujemy,
który z nich jest prawdziwy, a wszystkie implikacje, a więc także alternatywy,
będą spełnione (dlaczego?). Jedynym przypadkiem, gdy ta metoda nie działa, jest
sytuacja, gdy dla pewnego
,
i
leżą w jednej silnie
spójnej składowej. W takim przypadku w ogóle nie istnieje żadne
rozwiązanie, gdyż implikacje są sprzeczne.
Widzimy, że główny koszt czasowy algorytmu jest generowany przez
znajdowanie silnie spójnych składowych i grafu tychże oraz przez sortowanie
topologiczne tego grafu. Wszystkie te operacje w standardowy sposób
wykonujemy za pomocą dwóch przeszukiwań w głąb (DFS). Koszt
jednego takiego przeszukiwania to
, gdzie
to
liczba wierzchołków, a
– liczba krawędzi grafu.
jest
w naszym przypadku równe
, a więc akceptowalne. Problemem
jest
. Krawędzie odpowiadające niewygodnemu
składnikowi
są jednak rozmieszczone regularnie wewnątrz
poszczególnych województw. Możemy zatem pamiętać dla każdego
wierzchołka jedynie jego „normalnych” sąsiadów, natomiast krawędzie
wynikające z przynależności do województwa wyznaczać na bieżąco,
w razie potrzeby. Będąc w dowolnym wierzchołku, możemy pójść
w przeszukiwaniu grafu dowolną krawędzią z jego listy krawędzi lub też krawędzią
z listy krawędzi województwa. Co do tych ostatnich, to jeśli zużywamy
krawędź „wojewódzką” z
do
, możemy spokojnie
założyć, że krawędzie „wojewódzkie” z
do
dla
wszystkich
są już niepotrzebne, i o nich zapomnieć. Jest tak, gdyż
wierzchołek
odwiedzamy raz, idąc z
, a wszystkie pozostałe
krawędzie do niego prowadzące już nam nie posłużą w przeszukiwaniu. Jeśli
rozmiar województwa to
, to zamiast
krawędzi
dla tego województwa pamiętamy tylko
końców tych
krawędzi i każdy koniec wykorzystujemy dokładnie raz, przy pierwszej
nadarzającej się okazji.
W ten sposób wykonujemy przeszukiwanie DFS w rozważanym grafie
w czasie
. Całe rozwiązanie ma złożoność czasową
i pamięciową
.