Przeskocz do treści

Delta mi!

Informatyczny kącik olimpijski

Trening

Tomasz Kulczyński

o artykule ...

  • Publikacja w Delcie: kwiecień 2010
  • Publikacja elektroniczna: 31-03-2011

Tym razem przyjrzymy się zadaniu Training z Międzynarodowej Olimpiady Informatycznej 2007.

Zadanie. Mamy dany spójny graf nieskierowany o math wierzchołkach z wyróżnionym drzewem rozpinającym (tzn. wyróżnione jest math krawędzi, które tworzą drzewo). Krawędzie spoza tego drzewa mają przypisane koszty. Należy przeciąć krawędzie o najmniejszej sumie kosztów, tak aby w grafie nie pozostał żaden cykl prosty (tzn. taki, w którym nie powtarzają się wierzchołki) długości parzystej. Krawędzi drzewowych nie wolno przecinać. Dodatkowo wiadomo, że stopień żadnego z wierzchołków grafu nie przekracza (niedużego) math

Krawędzie spoza drzewa będę nazywał poprzecznymi. Każda poprzeczna krawędź tworzy z naszym drzewem dokładnie jeden cykl (nazwijmy go cyklem poprzecznym). Jeśli cykl ten jest długości parzystej, musimy tę krawędź przeciąć, robimy więc to czym prędzej i nie zajmujemy się więcej taką krawędzią. Zauważmy, że w poprawnym rozwiązaniu możemy pozostawić cykle poprzeczne długości nieparzystej, ale tylko pod warunkiem, że żadne dwa z nich nie mają wspólnej krawędzi. Gdyby bowiem miały, to przez ich złączenie i usunięcie części wspólnej uzyskalibyśmy cykl prosty długości math przy czym mathmath są długościami tych cykli, a math – długością części wspólnej. Cykli poprzecznych bez wspólnych krawędzi nie da się w żaden sposób połączyć w cykl prosty. Zadanie sprowadza się więc do wybrania poprzecznych krawędzi, które możemy pozostawić, tak aby odpowiadające im cykle poprzeczne nie miały wspólnych krawędzi.

Do rozwiązania tak uproszczonego problemu użyjemy programowania dynamicznego. Ukorzeńmy nasze drzewo rozpinające. Dla każdego wierzchołka math i dla każdego podzbioru math synów math w naszym drzewie obliczymy math – największą możliwą sumę kosztów poprzecznych krawędzi, które możemy pozostawić, a których cykle są rozłączne krawędziowo i zawierają się całkowicie w podgrafie złożonym z krawędzi łączących math z wierzchołkami z math poddrzew wierzchołków z math oraz poprzecznych krawędzi.

Aby obliczyć math musimy zastanowić się nad cyklami poprzecznymi, które przechodzą przez math ale nie przechodzą przez ojca math Jeśli math jest pusty, to math W przeciwnym przypadku ustalmy pierwszego syna math Załóżmy, że istnieje cykl poprzeczny, który zawiera math i math ale nie zawiera ojca math Niech math będzie krawędzią poprzeczną tegoż cyklu, a math  – zbiorem jego wierzchołków. Wtedy przy obliczaniu math należy uwzględnić wyrażenie:

display-math(1)

przy czym mathoznacza zbiór wszystkich synów wierzchołka math Możemy też nie zdecydować się wziąć żadnego takiego cyklu, czemu odpowiada wyrażenie:

display-math(2)

Ostatecznie jako math weźmiemy maksimum z wartości (1) po odpowiednich parach math oraz (2).

Odpowiedzią w naszym zadaniu będzie

display-math

przy czym math jest sumą kosztów wszystkich krawędzi poprzecznych, a math – korzeniem drzewa.

Zastanówmy się nad złożonością czasową tego rozwiązania. Graf ma mathkrawędzi. Dla każdej krawędzi poprzecznej musimy znaleźć jej cykl w czasie mathco daje łączny koszt mathKażda krawędź poprzeczna math jest rozważana podczas programowania dynamicznego tylko dla wierzchołka math będącego najwyższym wierzchołkiem w drzewie, do którego sięga cykl poprzeczny zawierający math Stąd sumę po wierzchołkach tego cyklu, występującą w wyrażeniu (1), wystarczy obliczyć raz. Dla każdej pary math wybieramy albo brak krawędzi poprzecznych, albo też jedną z krawędzi, których cykle przechodzą przez math oraz pierwszego syna math w math ale nie przez ojca math Niech takich właśnie krawędzi poprzecznych będzie math a wszystkich krawędzi, których cykle przechodzą przez math ale nie przechodzą przez jego ojca – math Wtedy

display-math

Programowanie dynamiczne zajmuje więc czas mathplus obliczanie sum po wstawianych cyklach, którego koszt czasowy jest taki sam jak koszt szukania tych cykli. Stąd łączna złożoność czasowa to math przy zużyciu pamięci rzędu math