Динамічний мультиграф
Перегляд у форматі PDFНехай потрібно мати справу з незваженим неорієнтованим мультиграфом, причому в ньому дуже багато вершин і не дуже багато ребер. Причому, для повного щастя цей мультиграф динамічний, тобто змінний у часі: іноді приходять запити, що потрібно додати ребро між вершинами ~v[j]~ та ~v[k]~ (якщо ребро вже є – додати ще одне, на те і мультиграф) або вилучити ребро між вершинами ~v[j]~ та ~v[k]~ (якщо ребер кілька – має стати на одне менше; якщо одне – має не стати; якщо і так не було – так і лишається, що нема, бо навіть у мультиграфі кількість ребер не може бути від'ємною).
Раз «дуже багато вершин і не дуже багато ребер», однозначно не варто користуватися матрицею суміжності,
а слід користуватися деяким аналогом списків суміжності. Але якщо можливо, що з деяких вершин може виходити
по багато ребер, то при традиційній реалізації списків суміжності операція вилучення ребер буде надто повільною.
Тому в такій ситуації може бути доцільним поєднання ідеї списків суміжності з іншими, чим масив або List,
структурами даних. Як це найкраще робити мовою C# – питання відкрите, але, наприклад,
можна розглянути спосіб Dictionary<int,int>[], де кожен окремо взятий Dictionary<int,int> описує,
куди йдуть ребра з поточної вершини графа, причому ключами є номери тих вершин, куди йдуть ребра,
а значеннями – кількості таких ребер.)
Напишіть програму, яка оброблятиме послідовність запитів таких видів:
RESET_GRAPHnum – створити новий граф, що містить num вершин (з 0-ої по (num–1)-у) і не містить жодного ребра. Якщо перед цим вже зберігався якийсь граф, він знищується. Дія відбувається лише у пам'яті, нічого не виводиться.ADDj k – додати до неорієнтованого мультиграфа ребро ~\{v[j], v[k]\}~. Дія відбуваються лише у пам'яті, нічого не виводиться.DELj k – вилучити з неорієнтованого мультиграфа ребро ~\{v[j], v[k]\}~. Якщо це можливо, тобто між цими вершинами є хоча б одне ребро, то дія відбувається лише у пам'яті, на екран нічого не виводиться. Якщо це неможливо, тобто між цими вершинами нема жодного ребра, на екран виводиться повідомлення "CNNT" (великими літерами, скорочено від "CANNOT"), а дані в пам'яті не змінюються.CHKj k – перевірити, чи існує ребро, яке з'єднує вершини ~v[j]~ та ~v[k]~. Треба вивести велику латинську літеру "Y" або "N" (скорочено від "YES"/"NO"); дані в пам'яті при цьому не змінюються.CHECK_PATHj 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".
Коментарі