Advertisement
DaniDori

Графы

Nov 13th, 2023
759
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.96 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <limits>
  4. #include <queue>
  5.  
  6. using namespace std;
  7.  
  8. const int INF = numeric_limits<int>::max();
  9.  
  10. class Graph {
  11.     //ребро
  12.     struct Edge {
  13.         //откуда
  14.         int source;
  15.         //куда
  16.         int destination;
  17.         //вес
  18.         int weight;
  19.     };
  20.     //количество вершин
  21.     int V;
  22.     //матрица смежности(откуда, какие ребра)
  23.     vector<vector<Edge>> adjList;
  24.     //список ребер
  25.     vector<Edge> edges;
  26.  
  27. public:
  28.     Graph(int V) : V(V) {
  29.         //изменяем размер
  30.         adjList.resize(V);
  31.     }
  32.  
  33.     //Добавить вершину
  34.     void addEdge(int source, int destination, int weight) {
  35.         Edge edge = { source, destination, weight };
  36.         //относительно конкретной вершины(от которой ребро)
  37.         adjList[source].push_back(edge);
  38.         //просто список ребер
  39.         edges.push_back(edge);
  40.     }
  41.     //добавить вершину
  42.     void addNode() {
  43.         adjList.push_back(vector<Edge>());
  44.         V++;
  45.     }
  46.  
  47.     //вывод на экран построчной таблицы смежности
  48.     void displayGraph() {
  49.         for (int i = 0; i < V; ++i) {
  50.             cout << "Узел " << i + 1 << " связан с ребром \n";
  51.             for (Edge& edge : adjList[i]) {
  52.                 cout << "\tУзел " << edge.destination + 1 << " с весом ребра = " << edge.weight << "\n";
  53.             }
  54.             cout << "\n";
  55.         }
  56.     }
  57.    
  58.     //Найти Эксцентриситет
  59.     int findEccentricity(int node) {
  60.         vector<int> distances(V, INF);
  61.         distances[node] = 0;
  62.         //очередь
  63.         queue<int> q;
  64.         q.push(node);
  65.  
  66.         // Стандартная BFS(обход в ширину) для вычисления расстояний от узла до всех остальных узлов
  67.         while (!q.empty()) {
  68.             //достаем первую вершину из очереди
  69.             int u = q.front();
  70.             //достать из очереди
  71.             q.pop();
  72.  
  73.             for (auto& edge : adjList[u]) {
  74.                 //если нашли более короткий путь - обновляем
  75.                 if (distances[edge.destination] > distances[u] + edge.weight) {
  76.                     distances[edge.destination] = distances[u] + edge.weight;
  77.                     //вставить в очередь
  78.                     q.push(edge.destination);
  79.                 }
  80.             }
  81.         }
  82.         //находим самое большое расстояние в графе
  83.         int eccentricity = 0;
  84.         for (int dist : distances) {
  85.             if (dist != INF) {
  86.                 eccentricity = max(eccentricity, dist);
  87.             }
  88.         }
  89.  
  90.         return eccentricity;
  91.     }
  92.  
  93.     bool bellmanFord(int source, vector<int>& distances, vector<int>& predecessors) {
  94.         //Делаем массив длинны v и заполняем "бесконечностями"
  95.         distances.assign(V, INF);
  96.         //Делаем массив длинны v и заполняем -1
  97.         predecessors.assign(V, -1);
  98.         distances[source] = 0;
  99.  
  100.         for (int i = 0; i < V - 1; ++i) {
  101.             for (const Edge& edge : edges) {
  102.                 //Если этот проход еще не проверяли(там беск), и путь через вершину короче, чем есть - обновляем
  103.                 if (distances[edge.source] != INF && distances[edge.source] + edge.weight < distances[edge.destination]) {
  104.                     distances[edge.destination] = distances[edge.source] + edge.weight;
  105.                     predecessors[edge.destination] = edge.source;
  106.                 }
  107.             }
  108.         }
  109.  
  110.         // Проверка на наличие циклов с отрицательным весом
  111.         for (const Edge& edge : edges) {
  112.             if (distances[edge.source] != INF && distances[edge.source] + edge.weight < distances[edge.destination]) {
  113.                 return false; // Граф содержит цикл с отрицательным весом
  114.             }
  115.         }
  116.  
  117.         return true; // Циклы с отрицательным весом не найдены
  118.     }
  119.  
  120.     //печатает кратчайшие расстояния
  121.     void printPath(int source, int destination, const vector<int>& predecessors) {
  122.         if (source == destination) {
  123.             cout << source + 1;
  124.             return;
  125.         }
  126.         if (predecessors[destination] == -1) {
  127.             cout << "Путь от " << source + 1 << " до " << destination << " не существует.";
  128.             return;
  129.         }
  130.         printPath(source, predecessors[destination], predecessors);
  131.         cout << " -> " << destination;
  132.     }
  133. };
  134.  
  135. int main() {
  136.     setlocale(LC_ALL, "Russian");
  137.     int V = 8;
  138.     Graph g(V);
  139.     //создали граф из пунтка 10
  140.     g.addEdge(0, 1, 23);
  141.     g.addEdge(0, 2, 12);
  142.     g.addEdge(1, 0, 23);
  143.     g.addEdge(1, 2, 25);
  144.     g.addEdge(1, 4, 22);
  145.     g.addEdge(1, 7, 35);
  146.     g.addEdge(2, 0, 12);
  147.     g.addEdge(2, 1, 25);
  148.     g.addEdge(2, 3, 18);
  149.     g.addEdge(3, 2, 18);
  150.     g.addEdge(3, 5, 20);
  151.     g.addEdge(4, 1, 22);
  152.     g.addEdge(4, 5, 23);
  153.     g.addEdge(4, 6, 14);
  154.     g.addEdge(5, 3, 20);
  155.     g.addEdge(5, 4, 23);
  156.     g.addEdge(5, 6, 24);
  157.     g.addEdge(6, 4, 14);
  158.     g.addEdge(6, 5, 24);
  159.     g.addEdge(6, 7, 16);
  160.     g.addEdge(7, 1, 35);
  161.     g.addEdge(7, 6, 16);
  162.  
  163.     //вывели на экран
  164.     g.displayGraph();
  165.  
  166.     //выбираем первую вершину и относительно нее
  167.     int node = 1;
  168.     //считаем Эксцентриситет
  169.     cout << "Эксцентриситет узла " << node << " составляет: " << g.findEccentricity(node) << endl;
  170.  
  171.     vector<int> distances;
  172.     vector<int> predecessors;
  173.     //выбираем первую вершину и относительно нее считаем кратчайшие расстояния по Белману-Форду
  174.     int source = 1;
  175.     //если нет отрицательного цикла
  176.     if (g.bellmanFord(source, distances, predecessors)) {
  177.         //выписываем кратчайшие расстояния
  178.         cout << "Кратчайшие пути из узла " << source + 1 << " являются:" << endl;
  179.         for (int i = 0; i < V; ++i) {
  180.             cout << "Расстояние до " << i + 1 << " равно " << distances[i] << " и путь равен: ";
  181.             g.printPath(source, i, predecessors);
  182.             cout << endl;
  183.         }
  184.     }
  185.     else {
  186.         cout << "Граф содержит цикл с отрицательным весом" << endl;
  187.     }
  188.  
  189.     return 0;
  190. }
  191.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement