zliczyć liczbę spójnych składowych w grafie dla permutacji.
: 25 wrz 2015, o 17:58
Mamy permutację liczb \(\displaystyle{ 1...n}\). Konstruujemy graf wierzchołków \(\displaystyle{ 1...n}\) w ten sposób, że dwa wierzchołki są połączone (krawędź nieskierowana) wtw gdy są one w inwersji ze sobą.
Naszym zadaniem jest wymyślić algorytm, który dla danej permutacji policzy ile graf ma spójnych składowych:
Ja zaproponuję coś takiego: (proszę o sprawdzenie, ale także pokazanie alternatywnych rozwiązań).
To rozwiązanie działa w czasie \(\displaystyle{ O(n\log^*)}\)
Używamy Union find, na początku \(\displaystyle{ 1...n}\) to osobne zbiory.
1. Policzmy tablicę sufixową dla minimów. Tzn dla każdego sufixu znamy minimum.
2. Sprawdzamy jakie jest minimum na przedziale \(\displaystyle{ [1..n]}\). Okazuje się, że to \(\displaystyle{ p}\). Wówczas lecimy
od \(\displaystyle{ 1}\) do \(\displaystyle{ i-1}\) i wszystkie scalamy z \(\displaystyle{ p}\) - dostajemy jeden zbiór. Potem powtarzamy to samo, w konsekwencji jesteśmy w sytuacji takiej:
I teraz:
Bierzemy maximum - niebieska kropka - z grupki pierwszej. Porównujemy go z minimum grupki drugiej:
Jeśli niebieska kropka (max) jest większa niż czerwona (min) to mamy inwersję i scalamy (UNION) obie grupki. Jedną (mniejszą) z niebieskich kropek eliminujemy i kontynuujemy.
Jeśli niebieska kropka (max) jest mniejsza niż czerwona (min) to żaden element z pierwszej grupki nie jest w inwersji z żadną inną grupką. Dlatego zapominamy o pierwszej grupce. I postępujemy tak samo dalej.
Co teraz ? Teraz zliczamy ilość zbiorów.
Czy to jest ok ? Ma ktoś pomysł na szybszą implementację ?
Naszym zadaniem jest wymyślić algorytm, który dla danej permutacji policzy ile graf ma spójnych składowych:
Ja zaproponuję coś takiego: (proszę o sprawdzenie, ale także pokazanie alternatywnych rozwiązań).
To rozwiązanie działa w czasie \(\displaystyle{ O(n\log^*)}\)
Używamy Union find, na początku \(\displaystyle{ 1...n}\) to osobne zbiory.
1. Policzmy tablicę sufixową dla minimów. Tzn dla każdego sufixu znamy minimum.
2. Sprawdzamy jakie jest minimum na przedziale \(\displaystyle{ [1..n]}\). Okazuje się, że to \(\displaystyle{ p}\). Wówczas lecimy
od \(\displaystyle{ 1}\) do \(\displaystyle{ i-1}\) i wszystkie scalamy z \(\displaystyle{ p}\) - dostajemy jeden zbiór. Potem powtarzamy to samo, w konsekwencji jesteśmy w sytuacji takiej:
I teraz:
Bierzemy maximum - niebieska kropka - z grupki pierwszej. Porównujemy go z minimum grupki drugiej:
Jeśli niebieska kropka (max) jest większa niż czerwona (min) to mamy inwersję i scalamy (UNION) obie grupki. Jedną (mniejszą) z niebieskich kropek eliminujemy i kontynuujemy.
Jeśli niebieska kropka (max) jest mniejsza niż czerwona (min) to żaden element z pierwszej grupki nie jest w inwersji z żadną inną grupką. Dlatego zapominamy o pierwszej grupce. I postępujemy tak samo dalej.
Co teraz ? Teraz zliczamy ilość zbiorów.
Czy to jest ok ? Ma ktoś pomysł na szybszą implementację ?