Advertisement
shchuko

Chinese

Oct 4th, 2019
586
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.27 KB | None | 0 0
  1. #include <iostream>
  2. #include <fstream>
  3. #include <vector>
  4. #include <stack>
  5. #include <limits>
  6. #include <algorithm>
  7. #include <set>
  8.  
  9.  
  10. //#define DEBUG
  11.  
  12. #ifdef DEBUG
  13. #define OUT_FILE_NAME "stdout"
  14. #else
  15. #define OUT_FILE_NAME "chinese.out"
  16. #endif
  17.  
  18. #define IN_FILE_NAME "chinese.in"
  19.  
  20.  
  21. class Vertex {
  22. private:
  23.     class DistVertex {
  24.     public:
  25.         int weight;
  26.         int v_num;
  27.  
  28.         DistVertex() : DistVertex(-1, -1) {}
  29.  
  30.         DistVertex(int _num, int _weight) :
  31.                 v_num{ _num },
  32.                 weight{ _weight } { }
  33.  
  34.     };
  35.  
  36. public:
  37.     typedef std::vector<DistVertex>::iterator ChildIterator;
  38.     typedef enum { white, gray, black } Color;
  39.  
  40.     Color color = white;
  41.     std::vector<DistVertex> child;
  42.  
  43. };
  44.  
  45. typedef std::vector<Vertex> Graph;
  46.  
  47. void graphColorClear(Graph &graph) {
  48.     for (auto &item : graph) {
  49.         item.color = Vertex::Color::white;
  50.     }
  51. }
  52.  
  53. bool existWaysToAllVertexesDFS(Graph &graph, int root) {
  54.     std::set<int> visited;
  55.     if (graph[root].color != Vertex::Color::white)
  56.         return true;
  57.  
  58.     // DFSPair includes vertex number and iterator to the next child of vertex to see
  59.     typedef std::pair<int, Vertex::ChildIterator> DFSPair;
  60.     std::stack<DFSPair> stack;
  61.     graph[root].color = Vertex::Color::gray;
  62.     stack.emplace(root, graph[root].child.begin());
  63.  
  64.     while (!stack.empty()) {
  65.         DFSPair temp_pair = stack.top();
  66.         stack.pop();
  67.  
  68.         if (temp_pair.second == graph[temp_pair.first].child.end()) {
  69.             graph[temp_pair.first].color = Vertex::Color::black;
  70.             visited.emplace(temp_pair.first);
  71.         }
  72.         else {
  73.             stack.emplace(temp_pair.first, next(temp_pair.second));
  74.  
  75.             if (graph[temp_pair.second.operator*().v_num].color == Vertex::Color::white) {
  76.                 graph[temp_pair.second.operator*().v_num].color = Vertex::Color::gray;
  77.                 stack.emplace(temp_pair.second.operator*().v_num, graph[temp_pair.second.operator*().v_num].child.begin());
  78.             }
  79.         }
  80.     }
  81.  
  82.     graphColorClear(graph);
  83.  
  84.     return graph.size() == visited.size();
  85. }
  86.  
  87. void DFSTopSort(Graph &graph, int root, std::vector<int> &visit_order) {
  88.     if (graph[root].color != Vertex::Color::white) {
  89.         return;
  90.     }
  91.     graph[root].color = Vertex::Color::black;
  92.  
  93.     for (auto v_to : graph[root].child) {
  94.         if (graph[v_to.v_num].color == Vertex::Color::white) {
  95.             DFSTopSort(graph, v_to.v_num, visit_order);
  96.         }
  97.     }
  98.     visit_order.push_back(root);
  99. }
  100.  
  101. bool DFSComponentSearch(Graph &transposed_graph, int root, std::vector<int> &components, int component_num) {
  102.     if (transposed_graph[root].color != Vertex::Color::white) {
  103.         return false;
  104.     }
  105.  
  106.     transposed_graph[root].color = Vertex::Color::black;
  107.     components[root] = component_num;
  108.  
  109.     for (auto v_to : transposed_graph[root].child) {
  110.         if (transposed_graph[v_to.v_num].color == Vertex::Color::white) {
  111.             DFSComponentSearch(transposed_graph, v_to.v_num, components, component_num);
  112.         }
  113.     }
  114.     return true;
  115. }
  116.  
  117. int condensateByComponents(Graph &graph, std::vector<int> &components) {
  118.     Graph transposed_graph(graph.size());
  119.  
  120.     for (int i = 0; i < graph.size(); ++i) {
  121.         for (auto &item : graph[i].child) {
  122.             transposed_graph[item.v_num].child.emplace_back(i, item.weight);
  123.         }
  124.     }
  125.  
  126.     std::vector<int> visit_order;
  127.     for (int v_start = 0; v_start < graph.size(); ++v_start) {
  128.         DFSTopSort(graph, v_start, visit_order);
  129.     }
  130.     graphColorClear(graph);
  131.  
  132.     std::reverse(visit_order.begin(), visit_order.end());
  133.  
  134.     int component_num = 0;
  135.     for (int v : visit_order) {
  136.         if (DFSComponentSearch(transposed_graph, v, components, component_num)) {
  137.             component_num++;
  138.         }
  139.  
  140.     }
  141.     graphColorClear(transposed_graph);
  142.  
  143.     return component_num;
  144. }
  145.  
  146. long long calcMSTWeight(Graph &graph, int root) {
  147.     std::vector<int> edge_min_weight(graph.size(), std::numeric_limits<int>::max());
  148.     for (auto &v_start : graph) {
  149.         for (auto const &v_finish : v_start.child) {
  150.  
  151.             int v_weight = v_finish.weight;
  152.             int v_to = v_finish.v_num;
  153.             edge_min_weight[v_to] = (v_weight < edge_min_weight[v_to]) ? v_weight : edge_min_weight[v_to];
  154.         }
  155.     }
  156.  
  157.     long long mst_weight = 0;
  158.     for (int i = 0; i < graph.size(); ++i) {
  159.         mst_weight += (i != root) ? edge_min_weight[i] : 0;
  160.     }
  161.  
  162.     Graph zero_graph(graph.size());
  163.     for (int v_start = 0; v_start < graph.size(); ++v_start) {
  164.         for (int v_finish = 0; v_finish < graph[v_start].child.size(); ++v_finish) {
  165.  
  166.             int v_to = graph[v_start].child[v_finish].v_num;
  167.             int weight = graph[v_start].child[v_finish].weight;
  168.  
  169.             if (weight == edge_min_weight[v_to]) {
  170.                 zero_graph[v_start].child.emplace_back(v_to, 0);
  171.             }
  172.         }
  173.     }
  174.  
  175.     if (existWaysToAllVertexesDFS(zero_graph, root)) {
  176.         return mst_weight;
  177.     }
  178.  
  179.     std::vector<int> components(graph.size());
  180.     int components_count = condensateByComponents(zero_graph, components);
  181.  
  182.     Graph cond_graph(static_cast<unsigned long>(components_count));
  183.     for (int v_start = 0; v_start < graph.size(); ++v_start) {
  184.         for (auto const &v_finish : graph[v_start].child) {
  185.             int v_to = v_finish.v_num;
  186.             int weight = v_finish.weight;
  187.  
  188.             if (components[v_start] != components[v_to]) {
  189.                 cond_graph[components[v_start]].child.emplace_back(components[v_to], weight - edge_min_weight[v_to]);
  190.             }
  191.         }
  192.     }
  193.     return mst_weight + calcMSTWeight(cond_graph, components[root]);
  194. }
  195.  
  196. int main() {
  197.     std::ifstream fin(IN_FILE_NAME);
  198.  
  199.     uint32_t v_count, e_count;
  200.     fin >> v_count >> e_count;
  201.  
  202.     Graph graph(v_count);
  203.  
  204.     for (int i = 0; i < e_count; ++i) {
  205.         int v, w;
  206.         int weight;
  207.         fin >> v >> w >> weight;
  208.  
  209.         graph[v - 1].child.emplace_back(w - 1, weight);
  210.     }
  211.     fin.close();
  212.  
  213.     std::ofstream fout(OUT_FILE_NAME);
  214.  
  215.     if (existWaysToAllVertexesDFS(graph, 0)) {
  216.         fout << "YES\n" << calcMSTWeight(graph, 0) << '\n';
  217.     }
  218.     else {
  219.         fout << "NO\n";
  220.     }
  221.     fout.close();
  222.     return 0;
  223. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement