Задача с сайта e-olymp.com.
Условие
Дан связный неориентированный граф без петель и кратных ребер. Разрешается удалять из него ребра. Требуется получить дерево.
Входные данные
Выходные данные
Выведите [latex]n — 1[/latex] пару чисел — ребра, которые войдут в дерево. Ребра можно выводить в любом порядке.
Код
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
#include <algorithm> #include <iostream> #include <vector> using namespace std; /* Объявляем структуру Ребро, которой будем пользоваться для построения графа и дерева */ struct edge{ int x, y; //вершины edge(){} edge(int a, int b){ x = a; y = b; } }; int main() { int n, m; cin >> n >> m; vector <edge> graph (m); //ребра исходного графа vector <edge> tree; //ребра дерева vector <int> variety (n); //множество вершин /* variety[n] = m - вершина n принадлежит множеству m. Следующий цикл определяет для каждой вершины свое множество */ for (int i = 0; i < n; i++){ variety[i] = i; } /* Заполняем ребра исходного графа значениями из стандартного ввода */ for (int i = 0; i < m; i++){ int a, b; cin >> a >> b; graph[i].x = a; graph[i].y = b; } /* Проверяем вершины каждого ребра. Если вершины не принадлежат одному и тому же множеству, но такое ребро добавляем в наше дерево, а вершины помещаем в одно множество */ for (int i = 0; i < m; i++){ int a = graph[i].x; int b = graph[i].y; if (variety[a] != variety[b]){ tree.push_back(graph[i]); int old_variety = variety[b], new_variety = variety[a]; for (int j = 0; j < n; j++){ if (variety[j] == old_variety){ variety[j] = new_variety; } } } } for(int i = 0; i < n - 1; i++){ //по принципу построения дерева, оно содержит n-1 ребро cout << tree[i].x << " " << tree[i].y; if (i != n-2){ cout << endl; } } return 0; } |
Тесты
Ввод | Вывод |
4 4 1 2 2 3 3 4 4 1 |
1 2 2 3 3 4 |
6 7 1 2 2 3 3 4 4 5 5 6 6 1 |
1 2 2 3 3 4 4 5 5 6 |
6 5 1 2 2 3 3 4 4 5 5 6 |
1 2 2 3 3 4 4 5 5 6 |
4 5 4 3 2 4 2 3 1 2 1 3 |
4 3 2 4 1 2 |
6 9 1 2 1 3 1 5 2 5 2 4 3 5 3 6 4 5 5 6 |
1 2 1 3 1 5 2 4 3 6 |
Решение
Учитывая то, что по условию задачи нам дан связный неориентированный граф без петель и кратных ребер и то, что любое дерево с [latex]n[/latex] вершинами содержит [latex]n-1[/latex] ребро, то для получения дерева нужно удалить столько ребер, пока не останется [latex]n-1[/latex] ребро.
Данную задачу я решил, применяя упрощенный алгоритм Краскала, учитывая, что данное дерево не является взвешенным и сортировку применять не нужно. Для начала объявляем наш исходный граф используя вектор ребер (edge). Структура ребер является простой и содержит в себе только информацию о вершинах, которое ребро соединяет. Алгоритм Краскала заключается в том, что мы каждую вершину помещаем в свое множество. Затем при просмотре каждого ребра исходного графа мы проверяем принадлежат ли вершины ребра одному множеству. Если нет, то добавляем данное ребро в наше дерево (предварительно его создав с помощью вектора ребер), после добавления мы добавляем все вершины, которые принадлежали тому же множеству, что и вторая вершина ребра, в множество первой вершины. Если же вершины уже принадлежат одному множеству, то переходим к следующему этапу цикла. После этой процедуры нам достаточно вывести на экран значения из нашего дерева — это и будут необходимые ребра.
Для отправки комментария необходимо войти на сайт.