Advertisement
Guest User

Untitled

a guest
Apr 5th, 2020
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.05 KB | None | 0 0
  1. #include <vector>
  2. #include<iostream>
  3. #include<queue>
  4.  
  5. using namespace std;
  6. /* Чтобы можно было глобально определить массивы, в качестве размера нужно указывать
  7.  * константное целое число, поэтому определим N как максимально возможное число вершин */
  8. const int N = 100000;
  9.  
  10. int n, m; //количество вершин и ребер в графе
  11.  
  12. /* храним список смежности в виде массива векторов пар, то есть g[i] - это
  13.  * вектор пар вида (вершина, смежная с i; вес ребра) */
  14. vector<pair<int, int>> g[N];
  15. bool used[N];        // used[i] - была ли использована в остовном дереве вершина i
  16. int cur_mst = 0;     // текущая сумма весов на ребрах остовного дерева
  17. // вектор для хранения ответа - пары (ребро(пара); вес)
  18. vector<pair<pair<int, int>, int>> ans;
  19.  
  20. void prim() {
  21.     /* Приоритетная очередь - это структура данных, в которой элементы отсортированы по какому-либо
  22.      * приоритету.
  23.      * В качестве параметров указываем тип элементов, которые будут храниться в очереди (пара целых чисел,
  24.      * отображает ребро), тип контейнера для хранения элементов (вектор пар вида (вес, ребро(пара)), компаратор (функция для
  25.      * сравнения элементов, в данном случае более приоритетные - меньшие элементы) */
  26.     priority_queue<pair<int, pair<int, int>>, vector<pair<int, pair<int, int>>>, greater<pair<int, pair<int, int>>>> q;
  27.     // начинаем построение минимального остовного с вершины 0 (абстрактное ребро 0, 0)
  28.     // то есть как будто пришли в вершину 0 из самой себя по ребру с весом 0
  29.     q.push(make_pair(0, make_pair(0, 0)));
  30.    
  31.     while (!q.empty()) { // пока очередь не станет пустой
  32.         pair<int, pair<int, int>> c = q.top(); // достаем верхний элемент из очереди (то есть, с самым меньшим весом)
  33.         q.pop(); // удаляем его из очереди
  34.  
  35.         int w = c.first;         // вес текущего ребра
  36.         int v = c.second.first;  // вершина, в которую это ребро переходит
  37.         int p = c.second.second; // откуда идет ребро
  38.  
  39.         if (used[v]) continue; // если вершина v уже есть в остовном дереве, то это ребро не подходит
  40.        
  41.         used[v] = true; // помечаем вершину v как использованную
  42.         cur_mst += w;   // добавляем вес текущего ребра
  43.         if (p != v) // если это не абстрактное ребро из самого начала
  44.         // добавляем ребро в ответ, добавляем 1 к вершинам для перехода в 1-индексацию
  45.         ans.push_back(make_pair(make_pair(p + 1, v + 1), w));
  46.  
  47.         // проходим по всем смежным вершинам вершины v
  48.         for (pair<int, int> e : g[v]) {
  49.             int u = e.first;        // смежная вершина
  50.             int weight = e.second;  // вес ребра до нее
  51.  
  52.             if (!used[u]) {               // если вершины u еще нет в остовном дереве, добавим ее в очередь
  53.                 q.push(make_pair( weight, make_pair(u, v)));    // добавляем пару (вес; вершина). сначала идет вес, потому что сортируем по весу
  54.             }
  55.         }
  56.     }  
  57. }
  58.  
  59. int main() {
  60.     setlocale(LC_ALL, "rus");
  61.     cin >> n >> m;
  62.     // считываем все ребра
  63.     for (int i = 0; i < m; ++i) {
  64.         int a, b, w;  // a и b - вершины, w - вес ребра
  65.         cin >> a >> b >> w;
  66.         a--; b--; //переход в 0-индексацию
  67.         // добавляем пары вида (смежная вершина; вес ребра)
  68.         g[a].push_back(make_pair(b, w));
  69.         g[b].push_back(make_pair(a, w));
  70.     }
  71.  
  72.     prim(); // вызываем функцию поиска минимального остовного дерева по алгоритму Прима
  73.  
  74.     cout << "Сумма весов ребер минимального остовного дерева: " << cur_mst << endl;
  75.     cout << "Минимальное остовное дерево: " << endl;
  76.     // проходи по всем ребрам в ответе
  77.     for (auto edge : ans) {
  78.         cout << edge.first.first << " " << edge.first.second << " " << edge.second << endl;
  79.     }
  80. }
  81.  
  82. /*
  83. 6 8
  84. 1 2 7
  85. 2 3 5
  86. 1 4 4
  87. 4 3 7
  88. 2 4 9
  89. 4 5 10
  90. 3 5 13
  91. 5 6 11
  92. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement