Динамічний мультиграф

Перегляд у форматі PDF

Надіслати розв'язок

Бали: 3,00
Time limit: 1.0s
Memory limit: 256M
Input: stdin
Output: stdout

Problem type

Нехай потрібно мати справу з незваженим неорієнтованим мультиграфом, причому в ньому дуже багато вершин і не дуже багато ребер. Причому, для повного щастя цей мультиграф динамічний, тобто змінний у часі: іноді приходять запити, що потрібно додати ребро між вершинами ~v[j]~ та ~v[k]~ (якщо ребро вже є – додати ще одне, на те і мультиграф) або вилучити ребро між вершинами ~v[j]~ та ~v[k]~ (якщо ребер кілька – має стати на одне менше; якщо одне – має не стати; якщо і так не було – так і лишається, що нема, бо навіть у мультиграфі кількість ребер не може бути від'ємною).

Раз «дуже багато вершин і не дуже багато ребер», однозначно не варто користуватися матрицею суміжності, а слід користуватися деяким аналогом списків суміжності. Але якщо можливо, що з деяких вершин може виходити по багато ребер, то при традиційній реалізації списків суміжності операція вилучення ребер буде надто повільною. Тому в такій ситуації може бути доцільним поєднання ідеї списків суміжності з іншими, чим масив або List, структурами даних. Як це найкраще робити мовою C# – питання відкрите, але, наприклад, можна розглянути спосіб Dictionary<int,int>[], де кожен окремо взятий Dictionary<int,int> описує, куди йдуть ребра з поточної вершини графа, причому ключами є номери тих вершин, куди йдуть ребра, а значеннями – кількості таких ребер.)

Напишіть програму, яка оброблятиме послідовність запитів таких видів:

  • RESET_GRAPH num – створити новий граф, що містить num вершин (з 0-ої по (num–1)-у) і не містить жодного ребра. Якщо перед цим вже зберігався якийсь граф, він знищується. Дія відбувається лише у пам'яті, нічого не виводиться.
  • ADD j k – додати до неорієнтованого мультиграфа ребро ~\{v[j], v[k]\}~. Дія відбуваються лише у пам'яті, нічого не виводиться.
  • DEL j k – вилучити з неорієнтованого мультиграфа ребро ~\{v[j], v[k]\}~. Якщо це можливо, тобто між цими вершинами є хоча б одне ребро, то дія відбувається лише у пам'яті, на екран нічого не виводиться. Якщо це неможливо, тобто між цими вершинами нема жодного ребра, на екран виводиться повідомлення "CNNT" (великими літерами, скорочено від "CANNOT"), а дані в пам'яті не змінюються.
  • CHK j k – перевірити, чи існує ребро, яке з'єднує вершини ~v[j]~ та ~v[k]~. Треба вивести велику латинську літеру "Y" або "N" (скорочено від "YES"/"NO"); дані в пам'яті при цьому не змінюються.
  • CHECK_PATH j k – перевірити, чи існує шлях довільної довжини, який з'єднує вершини ~v[j]~ та ~v[k]~. Треба вивести слово "YES" або "NO" (великими літерами); дані в пам'яті при цьому не змінюються.

Вхідні дані

У вхідних даних записано послідовність запитів RESET_GRAPH, ADD, DEL, CHK та CHECK_PATH – кожен у окремому рядку, згідно вищеописаного формату. Першим гарантовано йде RESET_GRAPH, далі порядок запитів довільний. При кожному запиті ADD, DEL, CHK або CHECK_PATH вказуються два різні номери вершин від 0 до num–1, де num – кількість вершин поточного графа (згідно останнього виконаного запиту RESET_GRAPH). Кількість запитів ніде не вказана. Відомо, що при перевірці на великих вхідних даних запитів ADD, DEL та CHK буде дуже багато, а запитів RESET_GRAPH та CHECK_PATH – лише по кілька штук.

Результати

Виведіть повідомлення згідно описаних у форматах запитів правил. Кожне повідомлення слід виводити в окремому рядку.

Приклади

Вхід

RESET_GRAPH 3
ADD 0 1
ADD 0 1
ADD 1 2
CHK 0 2
CHECK_PATH 0 2
DEL 1 2
DEL 1 2
ADD 0 2
RESET_GRAPH 7
CHECK_PATH 0 2

Результат

N
YES
CNNT
NO

Примітки

В першому тесті:

  • відповідь "N" (однолітерна) видається на запит "CHK 0 2",
  • "YES" – на запит "CHECK_PATH 0 2",
  • "CNNT" – на другий із запитів "DEL 1 2",
  • "NO" (слово) – на останній із запитів "CHECK_PATH 0 2".

Коментарі

Please read the guidelines before commenting.


Ще немає коментарів.