To jest zadanie interaktywne.
Tło zadania
Po pół roku sklep pana I ostatecznie przestał się utrzymywać. Pan I postanowił go odstąpić i zostać odkrywcą, aby badać rozległy, nieznany świat.
Kierując się starą księgą, znalazł w głębi wielkiej pustyni podziemny pałac stworzony przez nieznaną cywilizację. Pałac składa się z $N$ wielkich jaskiń i $M$ dwukierunkowych przejść łączących te jaskinie. Dzięki księdze pan I potrafi rozpoznać jaskinię, w której się znajduje, ale nie opisano w niej układu $M$ przejść. Utrudnia mu to szukanie nieprzebranych skarbów, które według legendy są ukryte w pałacu.
Teraz jednak pan I odkrył tajemniczy mechanizm, pozwalający uzyskiwać informacje o pałacu. Postanowił go wykorzystać do poznania układu połączeń. Pomóż mu w tym.
Treść zadania
Podziemny pałac można przedstawić jako nieskierowany graf prosty o $N$ wierzchołkach i $M$ krawędziach (w grafie prostym dowolne dwa wierzchołki są połączone bezpośrednio najwyżej jedną krawędzią). Jaskinie są ponumerowane od $0$ do $n-1$. Obecnie nie znasz krawędzi tego grafu.
Każda jaskinia ma źródło światła, które może być włączone lub wyłączone. Jaskinia jest oświetlona tylko wtedy, gdy jej źródło światła jest włączone. Początkowo wszystkie źródła światła są wyłączone, a ich stan można zmieniać wyłącznie za pomocą mechanizmu odkrytego przez pana I. Mechanizm umożliwia wykonanie czterech operacji:
- Podajesz mechanizmowi numer $x$. Mechanizm zmienia stan źródła światła w jaskini $x$ oraz we wszystkich jaskiniach połączonych z nią bezpośrednim przejściem. Włączone źródła zostają wyłączone, a wyłączone zostają włączone.
- Podajesz mechanizmowi numer $x$. Mechanizm pokazuje bieżący stan źródła światła w jaskini $x$.
- Podajesz mechanizmowi dwa numery $x,y$, deklarując, że wiesz o istnieniu przejścia łączącego jaskinie $x$ i $y$, i polecasz mu je zapisać.
- Podajesz mechanizmowi numer $x$. Mechanizm sprawdza, czy zapisano już wszystkie przejścia połączone z jaskinią $x$.
Mechanizm może rozpocząć następną operację dopiero po zakończeniu poprzedniej. Nie można korzystać z niego dowolnie: liczby wywołań poszczególnych operacji są ograniczone odpowiednio przez $L_m,L_q,M,L_c$. Napisz program pomagający panu I rozsądnie korzystać z mechanizmu, aby poprawnie odnaleźć wszystkie $M$ przejść.
Szczegóły implementacji
Nie musisz i nie powinieneś implementować funkcji głównej. Zaimplementuj jedynie funkcję explore(N, M), gdzie N i M oznaczają odpowiednio liczbę jaskiń i przejść. Z biblioteką interaktywną możesz komunikować się za pomocą następujących czterech funkcji:
1. modify(x)
- Ta funkcja wykonuje operację 1 dla numeru $x$.
- Musisz zapewnić $0\le x<N$. Funkcja nie zwraca wartości.
2. query(x)
- Ta funkcja wykonuje operację 2 dla numeru $x$.
- Musisz zapewnić $0\le x<N$. Funkcja zwraca 0 lub 1, oznaczając odpowiednio, że źródło światła w jaskini $x$ jest obecnie wyłączone (0) lub włączone (1).
3. report(x, y)
- Ta funkcja wykonuje operację 3 dla numerów $x,y$.
- Musisz zapewnić $0\le x,y<N$ oraz $x\ne y$. Funkcja nie zwraca wartości.
4. check(x)
- Ta funkcja wykonuje operację 4 dla numeru $x$.
- Musisz zapewnić $0\le x<N$. Funkcja zwraca 0 lub 1; zwraca 1 wtedy i tylko wtedy, gdy wszystkie przejścia połączone z jaskinią $x$ zostały już zapisane za pomocą operacji 3.
Podczas oceniania biblioteka interaktywna wywoła explore dokładnie raz.
Gwarantuje się, że używany graf jest całkowicie ustalony przed rozpoczęciem interakcji i nie jest konstruowany dynamicznie na podstawie interakcji z Twoim programem. Operacje interaktywne w tym zadaniu są zatem deterministyczne i nie musisz interesować się szczegółami ich implementacji w bibliotece.
Gwarantuje się, że przy przestrzeganiu limitów wywołań czas działania biblioteki interaktywnej nie przekracza 1 s. Ilość pamięci używanej przez bibliotekę jest stała i nie przekracza 128 MB.
Sposób implementacji
W katalogu roboczym zawodnika udostępniono plik template_explore.cpp/c/pas. Skopiuj go, zmień nazwę na explore.cpp/c/pas i napisz rozwiązanie na jego podstawie.
1. Dla zawodników używających C++ / C
- Upewnij się, że na początku programu znajduje się
#include "explore.h". - Interfejs funkcji
explore, którą należy zaimplementować, jest następujący:
void explore(int N, int M);
- Dostępne funkcje interaktywne mają następujące interfejsy:
void modify(int x);
int query(int x);
void report(int x, int y);
int check(int x);
2. Dla zawodników używających Pascala
- Uwaga: składnia implementowania interfejsu w Pascalu jest dość złożona. Napisz rozwiązanie bezpośrednio na podstawie dostarczonego pliku
template_explore.pas, zamiast implementować kod od zera. - Interfejs funkcji
explore, którą należy zaimplementować, jest następujący:
procedure _explore(N, M : longint);
- Uwaga: nazwa tej funkcji to
_explore, a nieexplore. Użycieexplorespowoduje błąd kompilacji. - Dostępne funkcje interaktywne mają następujące interfejsy:
procedure modify(x : longint);
function query(x : longint) : longint;
procedure report(x : longint; y : longint);
function check(x : longint) : longint;
Testowanie programu
Pliki grader.cpp/c i graderhelperlib.pas w katalogu zadania stanowią dostarczoną przez nas referencyjną implementację biblioteki interaktywnej. Implementacja używana podczas końcowych testów różni się od niej, dlatego rozwiązanie nie powinno zależeć od implementacji biblioteki.
1. Dla zawodników używających C/C++
- Aby skompilować plik wykonywalny, użyj w katalogu tego zadania poniższego polecenia.
- Dla C:
gcc grader.c explore.c -o explore -O2 -lm - Dla C++:
g++ grader.cpp explore.cpp -o explore -O2 -lm
2. Dla zawodników używających Pascala
- Aby skompilować plik wykonywalny, użyj w katalogu tego zadania poniższego polecenia:
fpc grader.pas -o"explore" -O2
3. Dla otrzymanego pliku wykonywalnego
- Plik wykonywalny odczytuje ze standardowego wejścia dane w następującym formacie:
Pierwszy wiersz zawiera trzy liczby całkowite $L_m,L_q,L_c$, a drugi wiersz dwie liczby całkowite $N,M$, o znaczeniu opisanym w treści zadania.
Każdy z kolejnych $M$ wierszy zawiera dwie liczby całkowite $x,y$, opisujące przejście łączące jaskinie $x$ i $y$.
- Po wczytaniu danych biblioteka interaktywna wywoła funkcję
exploredokładnie raz, testując Twoją funkcję na wczytanych danych. Gdy funkcja poprawnie zakończy działanie, biblioteka sprawdzi poprawność obliczeń. Jeśli są poprawne, wypiszeCorrectoraz informacje o liczbach wywołań funkcji interaktywnych; w przeciwnym razie wypisze odpowiedni komunikat o błędzie.
Interakcja
Załóżmy, że plik wykonywalny wczytał następujące dane:
100 200 300 3 2 0 1 1 2
Trzy liczby całkowite w pierwszym wierszu określają limity liczby wywołań trzech operacji: modify(x) można wywołać najwyżej 100 razy, query(x) najwyżej 200 razy, a check(x) najwyżej 300 razy.
Dwie liczby całkowite w drugim wierszu określają liczbę jaskiń i przejść: $N=3$, $M=2$.
Liczba wywołań report(x, y) nie może przekroczyć $M$, czyli w tym przykładzie 2.
Poniżej przedstawiono poprawny przebieg interakcji:
| Program zawodnika | Biblioteka interaktywna | Objaśnienie |
|---|---|---|
Wywołuje explore(3, 2) |
Początek testu | |
Wywołuje modify(0) |
Wykonuje operację 1 dla jaskini 0 | |
Wywołuje query(2) |
Zwraca 0 | Źródło światła w jaskini 2 jest obecnie wyłączone |
Wywołuje report(0, 1) |
Odkryto i zapisano przejście $(0,1)$ | |
Wywołuje check(0) |
Zwraca 1 | Wszystkie przejścia związane z jaskinią 0 zostały zapisane |
Wywołuje report(2, 1) |
Odkryto i zapisano przejście $(2,1)$ | |
| Kończy działanie i powraca | Wypisuje na ekranie Correct |
Interakcja zakończona, wynik poprawny |
Opis dostarczonych plików
W katalogu tego zadania:
grader.cpp/cigraderhelperlib.pasto dostarczona przez nas referencyjna implementacja biblioteki interaktywnej.explore.higrader.pasto pliki nagłówkowe; nie musisz interesować się ich zawartością.template_explore.cpp/c/pasto dostarczone przez nas przykładowe pliki źródłowe rozwiązania.explore1.in,explore2.iniexplore3.into przykładowe dane wejściowe do testowania.
Zawodnicy powinni wykonać kopie zapasowe wszystkich dostarczonych plików. Ocenianiu podlega jedynie explore.c/cpp/pas z katalogu tego zadania. Zmiany w pozostałych plikach nie mają wpływu na ocenianie.
Podzadania
Podczas końcowego oceniania pobierany jest jedynie plik explore.cpp/c/pas. Modyfikowanie innych plików w katalogu zawodnika nie wpływa na ocenianie.
Obowiązują przede wszystkim takie same ograniczenia jak w zadaniach tradycyjnych. Na przykład błąd kompilacji skutkuje otrzymaniem 0 punktów za całe zadanie, a błąd wykonania, przekroczenie limitu czasu lub pamięci itp. skutkują otrzymaniem 0 punktów za odpowiedni test. Możesz odwoływać się jedynie do zdefiniowanych przez siebie zmiennych oraz zmiennych udostępnionych przez bibliotekę interaktywną i odpowiadających im obszarów pamięci. Próba dostępu do innych obszarów może spowodować błąd kompilacji lub wykonania.
Poza powyższymi warunkami otrzymasz pełną liczbę punktów za test wtedy i tylko wtedy, gdy:
- Każde wywołanie funkcji jest poprawne, a liczby wywołań
modify,queryichecknie przekraczają odpowiednio $L_m,L_q,L_c$. - Ponieważ limit wywołań
reportwynosi $M$, każde wywołanie musi zapisywać nową, istniejącą krawędź. Przy każdym wywołaniureport(x, y)musi zatem istnieć przejście łączące jaskinie $x$ i $y$, a przed tym wywołaniem nie mogło wystąpić anireport(x, y), anireport(y, x). - Zaimplementowana przez Ciebie funkcja
explorekończy działanie w zwykły sposób. - W chwili zakończenia funkcji
explorewszystkie $M$ przejść zostały już zapisane za pomocą wywołańreport.
Ograniczenia
Zadanie zawiera 25 testów, każdy wart 4 punkty. Rozmiary danych i związane z nimi ograniczenia dla każdego testu podano w poniższej tabeli.
| Numer testu | $N=$ | $M=$ | $L_m=$ | $L_q=$ | $L_c=$ | Szczególne właściwości |
|---|---|---|---|---|---|---|
| 1 | $3$ | $2$ | $100$ | $100$ | $100$ | Brak |
| 2 | $100$ | $10N$ | $200$ | $10^4$ | $2M$ | Brak |
| 3 | $200$ | $10N$ | $200$ | $4\times10^4$ | $2M$ | Brak |
| 4 | $300$ | $10N$ | $299$ | $9\times10^4$ | $2M$ | Brak |
| 5 | $500$ | $10N$ | $499$ | $1.5\times10^5$ | $2M$ | Brak |
| 6 | $59998$ | $N/2$ | $17N$ | $17N$ | $0$ | A |
| 7 | $99998$ | $N/2$ | $18N$ | $18N$ | $0$ | A |
| 8 | $199998$ | $N/2$ | $19N$ | $19N$ | $0$ | A |
| 9 | $199998$ | $N/2$ | $19N$ | $19N$ | $0$ | A |
| 10 | $99997$ | $N-1$ | $18N$ | $18N$ | $0$ | B |
| 11 | $199997$ | $N-1$ | $19N$ | $19N$ | $0$ | B |
| 12 | $99996$ | $N-1$ | $10^7$ | $10^7$ | $2M$ | C |
| 13 | $199996$ | $N-1$ | $10^7$ | $10^7$ | $2M$ | C |
| 14 | $199996$ | $N-1$ | $10^7$ | $10^7$ | $2M$ | C |
| 15 | $99995$ | $N-1$ | $10^7$ | $10^7$ | $2M$ | D |
| 16 | $99995$ | $N-1$ | $10^7$ | $10^7$ | $2M$ | D |
| 17 | $199995$ | $N-1$ | $10^7$ | $10^7$ | $2M$ | D |
| 18 | $1004$ | $2000$ | $10^7$ | $5\times10^4$ | $2M$ | Brak |
| 19 | $1004$ | $3000$ | $10^7$ | $5\times10^4$ | $2M$ | Brak |
| 20 | $1004$ | $3000$ | $10^7$ | $5\times10^4$ | $2M$ | Brak |
| 21 | $50000$ | $2N$ | $10^7$ | $10^7$ | $2M$ | Brak |
| 22 | $100000$ | $2N$ | $10^7$ | $10^7$ | $2M$ | Brak |
| 23 | $150000$ | $200000$ | $10^7$ | $10^7$ | $2M$ | Brak |
| 24 | $200000$ | $250000$ | $10^7$ | $10^7$ | $2M$ | Brak |
| 25 | $200000$ | $300000$ | $10^7$ | $10^7$ | $2M$ | Brak |
Przypominamy, że graf używany podczas testowania jest całkowicie ustalony przed rozpoczęciem interakcji i nie jest konstruowany dynamicznie na podstawie interakcji z Twoim programem.
Oznaczenia w kolumnie szczególnych właściwości mają następujące znaczenie:
A: Gwarantuje się, że stopień każdego wierzchołka wynosi dokładnie $1$.
B: Gwarantuje się, że dla każdego $x>0$ istnieje dokładnie jedno $y<x$, dla którego jaskinie $x$ i $y$ są połączone bezpośrednim przejściem.
C: Istnieje permutacja $p_0,p_1,\ldots,p_{N-1}$ liczb od $0$ do $N-1$, taka że dla każdego $1\le i<N$ istnieje przejście łączące jaskinie $p_{i-1}$ i $p_i$.
D: Gwarantuje się, że graf jest spójny.
- Wskazówka: Twój program może odróżniać powyższe rodzaje danych na podstawie cyfry jedności otrzymanego parametru $N$.