Przeskocz do treści

Delta mi!

Informatyczny kącik olimpijski

Telekomunikacja

Bartosz Łukasiewicz

o artykule ...

  • Publikacja w Delcie: lipiec 2019
  • Publikacja elektroniczna: 1 lipca 2019
  • Wersja do druku [application/pdf]: (290 KB)

W tym odcinku omówimy rozwiązanie zadania "Telekomunikacja", które pojawiło się na drugim etapie Zawodów Drużynowych XIII Młodzieżowej Olimpiady Informatycznej.

Zadanie (Telekomunikacja). W pewnym państwie znajduje się n miast ponumerowanych kolejnymi liczbami naturalnymi od |1 do |n. W każdym mieście znajduje się jedna wieża telekomunikacyjna. Wieża w i-tym mieście jest przystosowana do nadawania i odbierania fal na częstotliwości  f i herców. Dotychczas wszystkie miasta komunikowały się bardzo chaotycznie, dlatego postanowiono to uporządkować. Bezpośrednia komunikacja ma być ograniczona do wybranej sieci połączeń. Sieć ma składać się z |n− 1 połączeń pomiędzy miastami oraz ma być spójna (innymi słowy ma tworzyć drzewo). Wartością połączenia pomiędzy miastami u i |v nazywamy największy wspólny dzielnik liczb | fu i | fv. Król chce wybrać taką sieć, aby suma wartości połączeń była maksymalna. Pomóż mu i podaj tę wartość.

Wstęp

Zacznijmy od opisania zadania jako problemu grafowego. Dany jest graf pełny =(V,E),G gdzie:

  • V = {1,2,...,n},
  • E = {(u,v) u,v ∈ V ∧ u=/v}.

Wagą krawędzi |(u,v)∈ E jest NWD(f , f ). u v Chcemy znaleźć sumę wag krawędzi maksymalnego drzewa rozpinającego.

obrazek

Przykładowo, jeśli mamy cztery miasta, w których wieże nadają z częstotliwościami:  f1 = 8, f2 = 9, f3 = 12, f4 = 6, to graf wygląda następująco (linie ciągłe oznaczają krawędzie maksymalnego drzewa rozpinającego, a suma wag tych krawędzi wynosi 4 +3 + 6 = 13 ).
Niech =max f. |M u>Vu

Rozwiązanie |O

W pierwszym kroku tego rozwiązania zbudujmy wyżej opisany graf, który ma n wierzchołków i n -n−1- 2 krawędzi. Wagę dowolnej krawędzi |(u,v)∈ E możemy obliczyć za pomocą algorytmu Euklidesa, który działa w czasie O(log(fu Zatem cały graf zbudujemy w czasie )).O(n2

Znajdowanie minimalnego drzewa rozpinającego to znany problem, który może zostać rozwiązany za pomocą jednego z algorytmów: Prima, Kruskala lub Borůvki. Do znalezienia maksymalnego drzewa rozpinającego wykorzystamy zmodyfikowany algorytm Kruskala. Na początku mamy las drzew, gdzie każdy wierzchołek stanowi osobne drzewo. Następnie przeglądamy wszystkie krawędzie w kolejności nierosnących wag. Jeśli rozpatrywana krawędź łączy dwa różne drzewa, to dodajemy ją do drzewa rozpinającego. Sprawdzanie, czy dwa wierzchołki należą do różnych drzew, możemy zrealizować za pomocą struktury zbiorów rozłącznych. Czas wykonania n -n−21- operacji (dla każdej krawędzi) na |n-elementowym zbiorze wierzchołków wynosi O(n2 gdzie log∗ oznacza logarytm iterowany, czyli liczbę operacji logarytmowania potrzebną do uzyskania wyniku nie większego od 1. Algorytm wybierze |n− 1 krawędzi, które tworzą maksymalne drzewo rozpinające. Całkowity czas działania algorytmu wynosi |O(n2 (dominujące jest sortowanie krawędzi po wadze). Jeśli wykorzystamy sortowanie przez zliczanie, to otrzymamy czas 2∗ +n⋅log(n))O(M . Dowód poprawności algorytmu pozostawiamy Czytelnikowi jako ćwiczenie (dowód jest analogiczny do dowodu algorytmu Kruskala).

Rozwiązanie |O

W tym rozwiązaniu nie będziemy jawnie konstruowali grafu, natomiast postaramy się szybko znajdować krawędzie maksymalnego drzewa rozpinającego. Zauważmy, że NWD(fu, fv) ⩽ min(f u, fv) dla dowolnych u, v∈ V . Zatem krawędzie incydentne z wierzchołkiem | u ∈V mogą mieć co najwyżej wagę | fu. Na mocy obserwacji połączmy w drzewa wierzchołki o tej samej częstotliwości. Niech Sx = {u ∈V fu = x}. Teraz, dla każdego naturalnego ]x∈ [1;M wierzchołki Sx łączymy w drzewo. Wystarczy np. do wybranego wierzchołka podłączyć pozostałe, tworząc  Sx − 1 nowych krawędzi o wadze |x każda. W dalszej części rozwiązania możemy uwzględnić tylko reprezentantów otrzymanych drzew, ponieważ każdy wierzchołek w drzewie ma taki sam zestaw wag krawędzi. Wówczas nie ma dwóch wierzchołków o tym współczynniku.

W zmodyfikowanym algorytmie Kruskala przeglądamy krawędzie w kolejności nierosnących wag. Zatem dla każdego d od |M do 1 znajdźmy wierzchołki, które mogą być połączone krawędzią o wadze d. Są to wierzchołki z etykietami: d, 2d,3d,...,⌊M-⌋d d (wielokrotności d nie większe niż M ). Chcemy wszystkie te wierzchołki uspójnić (być może pomiędzy niektórymi wierzchołkami są już krawędzie wygenerowane wcześniej). Wystarczy, że wybierzemy jeden wierzchołek i podłączymy do niego te wierzchołki, które należą do innego drzewa.

Dla każdego |d rozpatrzymy ⌊ Md⌋ wierzchołków. Zatem w sumie rozpatrzymy ⋅log(M)) |O(M wierzchołków. Do sprawdzania spójności wykorzystujemy strukturę zbiorów rozłącznych. W celu szybkiego sprawdzania, czy istnieje wierzchołek z daną etykietą, wystarczy na początku zliczyć wystąpienia w czasie ). O(n Stąd całkowita złożoność wynosi ⋅log(M)⋅log∗(M)).O(n