Advertisement
AmbushedRaccoon

Алгоритм Дейкстры

Sep 8th, 2021
1,799
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.46 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <fstream>
  4. #include <vector>
  5. #include <limits>
  6. #include <stack>
  7.  
  8. const int INF = std::numeric_limits<int>::max();
  9.  
  10. struct Node
  11. {
  12.     int id;
  13. };
  14.  
  15. struct NodeWrapper
  16. {
  17.     Node* node;
  18.     bool visited = false;
  19.     int weight = INF;
  20.     NodeWrapper* prev_node = nullptr;
  21. };
  22.  
  23. struct Edge
  24. {
  25.     Node* start;
  26.     Node* end;
  27.     int weight;
  28. };
  29.  
  30. struct EdgeWrapper
  31. {
  32.     NodeWrapper* start;
  33.     NodeWrapper* end;
  34.     int weight;
  35. };
  36.  
  37. struct Graph
  38. {
  39.     std::vector<Node> nodes;
  40.     std::vector<Edge> edges;
  41. };
  42.  
  43. struct GraphWrapper
  44. {
  45.     std::vector<NodeWrapper> nodes;
  46.     std::vector<EdgeWrapper> edges;
  47.  
  48.     GraphWrapper(Graph& graph)
  49.     {
  50.         nodes.reserve(graph.nodes.size());
  51.         for (auto& node : graph.nodes)
  52.         {
  53.             nodes.push_back(NodeWrapper{ &node });
  54.         }
  55.         edges.reserve(graph.edges.size());
  56.         for (auto& edge : graph.edges)
  57.         {
  58.             auto start_iter = std::find_if(nodes.begin(), nodes.end(), [&edge](const auto& node_wrapper) { return edge.start == node_wrapper.node; });
  59.             auto end_iter = std::find_if(nodes.begin(), nodes.end(), [&edge](const auto& node_wrapper) { return edge.end == node_wrapper.node; });
  60.             edges.push_back(EdgeWrapper{ &(*start_iter), &(*end_iter), edge.weight });
  61.         }
  62.     }
  63. };
  64.  
  65. bool read_nodes(std::istream& is, int node_count, std::vector<Node>& nodes_out)
  66. {
  67.     nodes_out.clear();
  68.     for (int i = 0; i < node_count; i++)
  69.     {
  70.         Node node;
  71.         is >> node.id;
  72.         nodes_out.push_back(node);
  73.     }
  74.     return true;
  75. }
  76.  
  77. bool read_edges(std::istream& is, int edges_count, const std::vector<Node>& nodes, std::vector<Edge>& edges_out)
  78. {
  79.     edges_out.clear();
  80.     for (int i = 0; i < edges_count; i++)
  81.     {
  82.         decltype(Node::id) start_id, end_id;
  83.         decltype(Edge::weight) weight;
  84.  
  85.         is >> start_id >> end_id >> weight;
  86.         auto start_iter = std::find_if(nodes.begin(), nodes.end(), [start_id](const auto& node) {return node.id == start_id; });
  87.         auto end_iter = std::find_if(nodes.begin(), nodes.end(), [end_id](const auto& node) {return node.id == end_id; });
  88.  
  89.         if (start_iter == nodes.end() || end_iter == nodes.end())
  90.         {
  91.             edges_out.clear();
  92.             return false;
  93.         }
  94.  
  95.         edges_out.push_back(Edge
  96.             {
  97.                 const_cast<Node*>(&(*start_iter)),
  98.                 const_cast<Node*>(&(*end_iter)),
  99.                 weight
  100.             });
  101.     }
  102.     return true;
  103. }
  104.  
  105. Graph read_graph(const std::string& file_path)
  106. {
  107.     Graph result;
  108.     std::ifstream fin(file_path);
  109.     if (fin)
  110.     {
  111.         int nodes_count, edges_count;
  112.         fin >> nodes_count >> edges_count;
  113.         if (read_nodes(fin, nodes_count, result.nodes))
  114.         {
  115.             read_edges(fin, edges_count, result.nodes, result.edges);
  116.         }
  117.         fin.close();
  118.     }
  119.     return result;
  120. }
  121.  
  122. std::vector<NodeWrapper>::iterator find_next_node(std::vector<NodeWrapper>& nodes)
  123. {
  124.     auto result = nodes.end();
  125.     for (auto iter = nodes.begin(); iter != nodes.end(); ++iter)
  126.     {
  127.         if (result == nodes.end())
  128.         {
  129.             if (!(*iter).visited)
  130.             {
  131.                 result = iter;
  132.             }
  133.         }
  134.         else
  135.         {
  136.             if (!(*iter).visited && (*iter).weight < (*result).weight)
  137.             {
  138.                 result = iter;
  139.             }
  140.         }
  141.     }
  142.     return result;
  143. }
  144.  
  145. std::vector<Node*> find_path(Graph& graph, Node* start, Node* end)
  146. {
  147.     GraphWrapper wrapper(graph);
  148.     std::vector<Node*> path;
  149.     for (int i = 0; i < wrapper.nodes.size(); i++)
  150.     {
  151.         if (wrapper.nodes[i].node == start)
  152.         {
  153.             wrapper.nodes[i].weight = 0;
  154.         }
  155.     }
  156.  
  157.     auto min_iter = wrapper.nodes.end();
  158.  
  159.     do
  160.     {
  161.         min_iter = find_next_node(wrapper.nodes);
  162.         if (min_iter != wrapper.nodes.end())
  163.         {
  164.             for (int i = 0; i < wrapper.edges.size(); i++)
  165.             {
  166.                 if (wrapper.edges[i].start == &(*min_iter) && !wrapper.edges[i].end->visited)
  167.                 {
  168.                     if (wrapper.edges[i].start->weight + wrapper.edges[i].weight < wrapper.edges[i].end->weight)
  169.                     {
  170.                         wrapper.edges[i].end->weight = wrapper.edges[i].start->weight + wrapper.edges[i].weight;
  171.                         wrapper.edges[i].end->prev_node = wrapper.edges[i].start;
  172.                     }
  173.                 }
  174.             }
  175.             (*min_iter).visited = true;
  176.         }
  177.  
  178.     } while (min_iter != wrapper.nodes.end());
  179.  
  180.     auto end_iter = std::find_if(wrapper.nodes.begin(), wrapper.nodes.end(), [end](const auto& wrapper) {return wrapper.node == end; });
  181.     if (end_iter != wrapper.nodes.end())
  182.     {
  183.         NodeWrapper* current_node = &(*end_iter);
  184.         std::stack<NodeWrapper*> stack;
  185.         do
  186.         {
  187.             stack.push(current_node);
  188.             current_node = current_node->prev_node;
  189.         } while (current_node && current_node->weight != INF);
  190.  
  191.         while (!stack.empty())
  192.         {
  193.             path.push_back(stack.top()->node);
  194.             stack.pop();
  195.         }
  196.     }
  197.  
  198.     return path;
  199. }
  200.  
  201. int main()
  202. {
  203.     Graph graph = read_graph("input.txt");
  204.     auto path = find_path(graph, &graph.nodes[0], &graph.nodes[4]);
  205.  
  206.     for (Node* node : path)
  207.     {
  208.         std::cout << node->id << " ";
  209.     }
  210.  
  211.     return 0;
  212. }
  213.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement