Кожній картинці, зображеній на картах, поставимо у відповідність вершину графа. Кожній карті поставимо у відповідність неорієнтоване ребро, що з'єднує вершини, відповідні зображенням на її сторонах. Отриманий граф може бути незв'язним.
Відповідь на задачу буде possible, якщо в кожній компоненті зв'язності графа міститься не більше одного циклу. Компоненти зв'язності та кількість циклів у них можна визначити за допомогою системи неперетинних множин.
Приклад
Розглянемо чотири карти. Жовтим позначимо сторони карт, що звернені вгору. Кожному ребру графа поставимо у відповідність картинку, якою відповідна карта лежить вгору.
Розглянемо випадок з двома компонентами зв'язності:
Реалізація алгоритму
Визначимо масиви для обробки даних. Масив використовується для системи неперетинних множин. Якщо — представник множини, то has\_cycle[i] містить інформацію про кількість циклів у ній:
has\_cycle[i] = 0, циклів немає;
has\_cycle[i] = 1, є один цикл;
has\_cycle[i] > 1, є більше одного циклу;
#define MAX 50010
int dsu[2*MAX], has_cycle[2*MAX];Функція Repr повертає представника множини, що містить вершину .
int Repr(int n)
{
if (n == dsu[n]) return n;
return dsu[n] = Repr(dsu[n]);
}Функція Union об'єднує множини, що містять вершини та .
void Union(int x, int y)
{
int x1 = Repr(x), y1 = Repr(y);Якщо вершини та вже належать одній компоненті зв'язності (вони мають однакового представника), і при цьому додається ребро , то утворюється ще один цикл. У цьому випадку збільшуємо кількість циклів у представника цієї множини (x_1 — представник та ):
if (x1 == y1)
has_cycle[x1]++;Якщо та належать різним компонентам зв'язності, то виконуємо їх об'єднання, при цьому представник y_1 стає представником об'єднаної множини. У цьому випадку до кількості циклів компоненти з коренем y_1 додаємо кількість циклів компоненти з коренем x_1.
else
{
dsu[x1] = y1;
has_cycle[y1] += has_cycle[x1];
}
}Основна частина програми. Читаємо вхідні дані.
scanf("%d",&tests);
while (tests--)
{
scanf("%d",&n);Ініціалізуємо систему неперетинних множин.
for(i = 1; i <= 2*n; i++)
{
dsu[i] = i;
has_cycle[i] = 0;
}Будуємо систему неперетинних множин.
for (i = 0; i < n; i++)
{
scanf("%d %d",&p,&q);
Union(p,q);
}Перевіряємо, чи існує хоча б одна компонента зв'язності, що містить більше одного циклу.
for (i = 1; i <= 2*n; i++)
if (has_cycle[i] > 1) break;Виводимо відповідь.
printf("%s\n",((i <= 2 * n) ? "impossible" : "possible"));
}