Informatyczny kącik olimpijski
Przepływ w sieci
Jednym z zadań, które zostały postawione przed uczestnikami akademickich drużynowych zawodów programistycznych ACM ICPC Dhaka Regional Contest 2010, było zadanie o nieco mylącym tytule Network Flow (Przepływ w sieci).
Trochę zagmatwaną treść zadania można streścić w następujący sposób:
mamy dany
-wierzchołkowy graf nieskierowany
w którym
każdy z wierzchołków utożsamiamy z pewnym, zadanym punktem na
płaszczyźnie. Stopień każdego wierzchołka (czyli liczba krawędzi z nim
incydentnych) to
lub
Naszym zadaniem jest znaleźć taki
cykl Eulera w
(tj. cykl, który przechodzi każdą krawędzią dokładnie
raz), którego koszt jest minimalny. Kosztem cyklu nazywamy sumę kątów
pomiędzy każdą parą kolejnych krawędzi cyklu, przy czym interesują
nas najmniejsze kąty pomiędzy prostymi zawierającymi pary kolejnych
krawędzi.
Najprostszym rozwiązaniem jest przejrzenie wszystkich możliwości połączeń
par krawędzi w każdym wierzchołku stopnia
Dla każdego
układu połączeń sprawdzamy, czy tworzy on cykl Eulera, a jeśli tak, to
obliczamy jego koszt. Niestety, takie rozwiązanie ma złożoność czasową
Tak od razu nie widać metody na szybkie znalezienie
najtańszego cyklu Eulera, podejdźmy zatem do problemu od innej strony.
Możemy, na przykład, spróbować stworzyć jakikolwiek cykl Eulera,
a później stopniowo zmniejszać jego sumaryczny koszt. Autor tego
kącika nie ma jednak pomysłu na szybkie rozwiązanie problemu tym
sposobem.
Podejście odwrotne daje natomiast rezultaty. Spróbujmy utworzyć ze
wszystkich krawędzi grafu
możliwie najtańszy zbiór cykli,
a później najmniejszym kosztem pozmieniać połączenia w poszczególnych
wierzchołkach tak, by powstał cykl Eulera. Na początku w każdym wierzchołku
stopnia
łączymy krawędzie w pary tak, aby suma kosztów była jak
najmniejsza. W ten sposób otrzymujemy zbiór cykli
o minimalnym
możliwym koszcie. Zauważmy teraz, że jeśli dwa cykle
i
z tego zbioru przechodzą przez ten sam wierzchołek
to –
poprzez dowolną zamianę połączeń w wierzchołku
na inne – łączymy
te dwa cykle w jeden. Oznaczmy minimalny koszt takiej zmiany w wierzchołku
przez
Jeśli zaś zmienimy połączenia w wierzchołku,
który należy do jednego cyklu (przy czym cykl przechodzi przez niego
dwukrotnie), to albo nic się nie zmieni, albo podzielimy tenże cykl
na dwa.
Stwórzmy teraz nowy multigraf
w którym wierzchołkami są
cykle ze zbioru
a krawędziami wierzchołki stopnia
z
– przez każdy taki wierzchołek przechodzą wszakże dokładnie dwa
cykle (niekoniecznie różne). Kosztem krawędzi odpowiadającej wierzchołkowi
z
niech będzie
Szukamy najtańszego sposobu
połączenia wszystkich cykli w jeden, ale w multigrafie
odpowiada to
szukaniu zbioru krawędzi o minimalnym koszcie łączącego wszystkie
wierzchołki. Jest to zatem problem wyznaczenia najtańszego drzewa
rozpinającego w
Zauważmy, że gdyby krawędzie
mogły
mieć ujemne koszty, to takie rozwiązanie nie działałoby, gdyż, być może,
opłacałoby się wybrać, poza drzewem rozpinającym, jeszcze trochę krawędzi z
które zmniejszyłyby koszt. U nas jednak
dla każdego
wierzchołka
z
Znanych jest kilka efektywnych algorytmów
znajdujących minimalne drzewo rozpinające, np. algorytmy Kruskala i Prima,
działające dla grafu
w czasie
Całe
rozwiązanie zadania wymaga zbudowania grafu
(koszt liniowy),
a następnie znalezienia minimalnego drzewa rozpinającego w
co
możemy wykonać w czasie
Takie rozwiązanie w żaden
sposób nie korzysta ze specyfiki danych wejściowych, w szczególności
z geometrycznych własności grafu oraz sposobu obliczania kosztów. Autor
nie zna rozwiązania, które w istotny sposób korzystałoby z tych informacji,
zachęca więc Czytelnika do próby znalezienia takowego.