mfgnik

Untitled

Apr 29th, 2020
999
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.04 KB | None | 0 0
  1. #include <algorithm>
  2. #include <deque>
  3. #include <functional>
  4. #include <iostream>
  5. #include <istream>
  6. #include <memory>
  7. #include <numeric>
  8. #include <unordered_map>
  9. #include <utility>
  10. #include <vector>
  11.  
  12.  
  13. const int kInfinity = 2000000000;
  14.  
  15.  
  16. /*
  17.  Возвращает минимальное значение из полуинтервала [left; right) такое, что значение предиката истинно.
  18.  predicate(left) должен быть равен false, predicate(right) должен быть равен true.
  19.  Если по ошибке будет передан пустой полуинтервал, то будет возвращен right.
  20.  */
  21. template<typename T, class Predicate>
  22. T BinarySearch(T left, T right, Predicate predicate);
  23.  
  24. template<class Iterator>
  25. class IteratorRange {
  26. public:
  27.     IteratorRange(Iterator begin, Iterator end);
  28.  
  29.     Iterator begin() const;// NOLINT
  30.  
  31.     Iterator end() const;// NOLINT
  32.  
  33. private:
  34.     Iterator begin_, end_;
  35. };
  36.  
  37.  
  38.  
  39. struct Edge {
  40.     int source, destination;
  41.     Edge(int source, int destination);
  42.  
  43.     inline bool operator==(const Edge &other) const;
  44. };
  45.  
  46.  
  47. namespace std {
  48.     template<>
  49.     struct hash<Edge> {
  50.         inline size_t operator()(const Edge &edge) const {
  51.             std::hash<int> int_hasher;
  52.             return int_hasher(edge.source) ^ int_hasher(edge.destination);
  53.         }
  54.     };
  55. }// namespace std
  56.  
  57.  
  58. class Graph {
  59. public:
  60.     explicit Graph(int vertices);
  61.  
  62.     void AddEdge(int source, int destination);
  63.  
  64.     [[nodiscard]] size_t GetVerticesAmount() const;
  65.  
  66.     [[nodiscard]] IteratorRange<std::vector<Edge>::const_iterator> OutgoingEdges(int source) const;
  67.  
  68. private:
  69.     std::vector<int> vertices_;
  70.     std::vector<std::vector<Edge>> edges_;
  71. };
  72.  
  73. template<class Graph, class Visitor>
  74. void BFS(int origin, const Graph &graph, Visitor visitor);
  75.  
  76. class BfsVisitor {
  77. public:
  78.     virtual void ExamineEdge(const Edge &) = 0;
  79.     virtual bool Break() = 0;
  80.     virtual ~BfsVisitor() = default;
  81. };
  82.  
  83.  
  84. template<class Iterator, class Predicate>
  85. class FilterIterator {
  86. public:
  87.     FilterIterator(Iterator first, Iterator last, Predicate predicate);
  88.     auto operator*() const;
  89.     auto operator++();
  90.     auto operator!=(const FilterIterator &other) const;
  91.  
  92. private:
  93.     Iterator iter_, end_;
  94.     Predicate predicate_;
  95. };
  96.  
  97. template<class T, class Predicate>
  98. using FilterIteratorRange = IteratorRange < FilterIterator <
  99.         typename std::vector<T>::const_iterator, Predicate>>;
  100.  
  101. template<class Graph, class Predicate>
  102. class FilteredGraph {
  103. public:
  104.     FilteredGraph(const Graph &graph, Predicate predicate);
  105.  
  106.     size_t GetVerticesAmount() const;
  107.  
  108.     [[nodiscard]] FilterIteratorRange<Edge, Predicate> OutgoingEdges(int source) const;
  109.  
  110. private:
  111.     const Graph &graph_;
  112.     Predicate predicate_;
  113. };
  114.  
  115.  
  116. class FlowNetwork {
  117. public:
  118.     explicit FlowNetwork(int vertices);
  119.  
  120.     int GetSource() const;
  121.     int GetSink() const;
  122.  
  123.     size_t GetVerticesAmount() const;
  124.  
  125.     IteratorRange<std::vector<Edge>::const_iterator> OutgoingEdges(int source) const;
  126.  
  127.     int GetResidualCapacity(const Edge &edge) const;
  128.  
  129.     void ChangeFlow(const Edge &edge, int delta);
  130.  
  131.     auto ResidualNetworkView() const;
  132.  
  133. private:
  134.     int source_{}, sink_{};
  135.     std::unique_ptr<Graph> graph_;
  136.     std::vector<int> capacity_, flow_;
  137.     std::unordered_map<Edge, int> edges_;
  138.     friend class FlowNetworkBuilder;
  139. };
  140.  
  141. class FlowNetworkBuilder {
  142. public:
  143.     void SetVerticeAmount(int vertices);
  144.  
  145.     void SetEdgeAmount(int edges);
  146.  
  147.     void AddEdge(int source, int destination, int capacity);
  148.  
  149.     void AddEdgeInternal(int source, int destination, int capacity);
  150.  
  151.     void SetCapacity(const Edge &edge, int capacity);
  152.     void SetFlow(const Edge &edge, int flow);
  153.  
  154.     void SetValue(const Edge &edge, int value, std::vector<int> *vector);
  155.  
  156.     void Reset(int source, int sink);
  157.  
  158.     std::unique_ptr<FlowNetwork> Build();
  159.  
  160. private:
  161.     std::unique_ptr<FlowNetwork> flow_network_ptr_;
  162. };
  163.  
  164. class BfsVisitorLevel : public BfsVisitor {
  165. public:
  166.     BfsVisitorLevel(int sink, std::vector<int> *level);
  167.     bool Break();
  168.     void ExamineEdge(const Edge &edge) override;
  169.  
  170. private:
  171.     int sink_;
  172.     std::vector<int> *level_;
  173. };
  174.  
  175. class Dinic {
  176. public:
  177.     explicit Dinic(std::unique_ptr<FlowNetwork> flow_network);
  178.  
  179.     int MaxFlow();
  180.  
  181.     int CalculateAugmentingFlow(int vertex, int incoming_flow);
  182.  
  183. private:
  184.     std::unique_ptr<FlowNetwork> flow_network_;
  185.     std::vector<int> level_;
  186. };
  187.  
  188.  
  189. std::pair<std::vector<int>, std::vector<std::pair<int, int>>>
  190. ReadGoldAndTrusts(std::istream &in_stream = std::cin);
  191.  
  192. int CalculateOptimalDistribution(
  193.         const std::vector<int> &golds, const std::vector<std::pair<int, int>> &trusts);
  194.  
  195. std::unique_ptr<FlowNetwork> BuildFlowNetworkFromGoldAndTrusts(
  196.         const std::vector<int> &golds, const std::vector<std::pair<int, int>> &trusts, int middle);
  197.  
  198. void PrintOptimalDistribution(int distribution, std::ostream &out = std::cout);
  199.  
  200.  
  201. int main() {
  202.     std::ios_base::sync_with_stdio(false);
  203.     std::cin.tie(nullptr);
  204.     auto [golds, trusts] = ReadGoldAndTrusts();
  205.     PrintOptimalDistribution(CalculateOptimalDistribution(golds, trusts));
  206.     return 0;
  207. }
  208.  
  209. void PrintOptimalDistribution(int distribution, std::ostream &out) {
  210.     out << distribution;
  211. }
  212.  
  213. std::pair<std::vector<int>, std::vector<std::pair<int, int>>>
  214. ReadGoldAndTrusts(std::istream &in_stream) {
  215.     int people_amount, trusts_amount;
  216.     std::vector<int> golds;
  217.     std::vector<std::pair<int, int>> trusts;
  218.     in_stream >> people_amount >> trusts_amount;
  219.     golds.resize(people_amount);
  220.     for (auto &person : golds) {
  221.         in_stream >> person;
  222.     }
  223.     trusts.resize(trusts_amount);
  224.     for (auto &[from, to] : trusts) {
  225.         in_stream >> from >> to;
  226.     }
  227.     return {golds, trusts};
  228. }
  229.  
  230. std::unique_ptr<FlowNetwork> BuildFlowNetworkFromGoldAndTrusts(
  231.         const std::vector<int> &golds, const std::vector<std::pair<int, int>> &trusts, int middle) {
  232.     int people_amount = golds.size();
  233.     int source = 0;
  234.     int sink = people_amount + 1;
  235.  
  236.     FlowNetworkBuilder builder;
  237.  
  238.     builder.SetVerticeAmount(people_amount + 2);
  239.  
  240.     builder.SetEdgeAmount(2 * people_amount + trusts.size());
  241.  
  242.     for (int vertex = 0; vertex < people_amount; ++vertex) {
  243.         builder.AddEdge(source, vertex + 1, golds[vertex]);
  244.     }
  245.  
  246.     for (auto &[from, to] : trusts) {
  247.         builder.AddEdge(from, to, kInfinity);
  248.     }
  249.  
  250.     for (int vertex = 0; vertex < people_amount; ++vertex) {
  251.         builder.AddEdge(vertex + 1, sink, middle);
  252.     }
  253.  
  254.     builder.Reset(source, sink);
  255.  
  256.     return builder.Build();
  257. }
  258.  
  259. int CalculateOptimalDistribution(const std::vector<int> &golds,
  260.                                  const std::vector<std::pair<int, int>> &trusts) {
  261.  
  262.     int gold_sum = std::accumulate(golds.begin(), golds.end(), 0);
  263.  
  264.     int left = 0;
  265.  
  266.     int right = *std::max_element(golds.begin(), golds.end());
  267.  
  268.     return BinarySearch(left, right, [&](int middle) {
  269.         return gold_sum ==
  270.                Dinic(std::move(BuildFlowNetworkFromGoldAndTrusts(golds, trusts, middle))).MaxFlow();
  271.     });
  272. }
  273.  
  274.  
  275. template<class Iterator>
  276. IteratorRange<Iterator>::IteratorRange(Iterator begin, Iterator end) : begin_(begin), end_(end) {
  277. }
  278.  
  279.  
  280. template<class Iterator>
  281. Iterator IteratorRange<Iterator>::begin() const {// NOLINT
  282.     return begin_;
  283. }
  284.  
  285.  
  286. template<class Iterator>
  287. Iterator IteratorRange<Iterator>::end() const {// NOLINT
  288.     return end_;
  289. }
  290.  
  291.  
  292. template<typename T, class Predicate>
  293. T BinarySearch(T left, T right, Predicate predicate) {
  294.     while (right - left > 1) {
  295.         T middle = (right + left) / 2;
  296.         if (predicate(middle)) {
  297.             right = middle;
  298.         } else {
  299.             left = middle;
  300.         }
  301.     }
  302.     return right;
  303. }
  304.  
  305. Edge::Edge(int source, int destination) : source(source), destination(destination) {
  306. }
  307.  
  308. bool Edge::operator==(const Edge &other) const {
  309.     return source == other.source && destination == other.destination;
  310. }
  311.  
  312. Graph::Graph(int vertices) {
  313.     vertices_.resize(vertices);
  314.     edges_.resize(vertices);
  315.     std::iota(vertices_.begin(), vertices_.end(), 0);
  316. }
  317.  
  318. void Graph::AddEdge(int source, int destination) {
  319.     edges_[source].emplace_back(source, destination);
  320. }
  321.  
  322. IteratorRange<std::vector<Edge>::const_iterator> Graph::OutgoingEdges(int source) const {
  323.     return {edges_[source].begin(), edges_[source].end()};
  324. }
  325.  
  326. size_t Graph::GetVerticesAmount() const {
  327.     return vertices_.size();
  328. }
  329.  
  330. template<class Graph, class Visitor>
  331. void BFS(int origin, const Graph &graph, Visitor visitor) {
  332.     std::deque<int> processing_vertices{origin};
  333.     std::vector<bool> is_discovered(graph.GetVerticesAmount());
  334.     is_discovered[origin] = true;
  335.  
  336.     while (!processing_vertices.empty()) {
  337.         auto current = processing_vertices.front();
  338.         processing_vertices.pop_front();
  339.  
  340.         for (const auto &edge : graph.OutgoingEdges(current)) {
  341.             auto destination = edge.destination;
  342.             if (is_discovered[destination]) {
  343.                 continue;
  344.             }
  345.             is_discovered[destination] = true;
  346.             processing_vertices.push_back(destination);
  347.  
  348.             visitor.ExamineEdge(edge);
  349.  
  350.             if (visitor.Break()) {
  351.                 return;
  352.             }
  353.         }
  354.     }
  355. }
  356.  
  357.  
  358. template<class Iterator, class Predicate>
  359. FilterIterator<Iterator, Predicate>::FilterIterator(Iterator first, Iterator last,
  360.                                                     Predicate predicate)
  361.     : iter_(first), end_(last), predicate_(predicate) {
  362.     while (iter_ != end_ && !predicate_(*iter_)) {
  363.         ++iter_;
  364.     }
  365. }
  366.  
  367. template<class Iterator, class Predicate>
  368. auto FilterIterator<Iterator, Predicate>::operator*() const {
  369.     return *iter_;
  370. }
  371.  
  372. template<class Iterator, class Predicate>
  373. auto FilterIterator<Iterator, Predicate>::operator++() {
  374.     do {
  375.         ++iter_;
  376.     } while (iter_ != end_ && !predicate_(*iter_));
  377. }
  378.  
  379. template<class Iterator, class Predicate>
  380. auto FilterIterator<Iterator, Predicate>::operator!=(const FilterIterator &other) const {
  381.     return iter_ != other.iter_;
  382. }
  383.  
  384.  
  385. template<class Graph, class Predicate>
  386. size_t FilteredGraph<Graph, Predicate>::GetVerticesAmount() const {
  387.     return graph_.GetVerticesAmount();
  388. }
  389.  
  390. template<class Graph, class Predicate>
  391. FilterIteratorRange<Edge, Predicate>
  392. FilteredGraph<Graph, Predicate>::OutgoingEdges(int source) const {
  393.     auto iterator_range = graph_.OutgoingEdges(source);
  394.     auto filter_begin = FilterIterator(iterator_range.begin(), iterator_range.end(), predicate_);
  395.     auto filter_end = FilterIterator(iterator_range.end(), iterator_range.end(), predicate_);
  396.     return {filter_begin, filter_end};
  397. }
  398.  
  399. template<class Graph, class Predicate>
  400. FilteredGraph<Graph, Predicate>::FilteredGraph(const Graph &graph, Predicate predicate)
  401.     : graph_(graph), predicate_(predicate) {
  402. }
  403.  
  404. int FlowNetwork::GetSource() const {
  405.     return source_;
  406. }
  407.  
  408. int FlowNetwork::GetSink() const {
  409.     return sink_;
  410. }
  411.  
  412. IteratorRange<std::vector<Edge>::const_iterator> FlowNetwork::OutgoingEdges(int source) const {
  413.     return graph_->OutgoingEdges(source);
  414. }
  415.  
  416. void FlowNetwork::ChangeFlow(const Edge &edge, int delta) {
  417.     flow_.at(edges_.at(edge)) += delta;
  418.     flow_.at(edges_.at(edge) ^ 1) -= delta;
  419. }
  420.  
  421. int FlowNetwork::GetResidualCapacity(const Edge &edge) const {
  422.     return capacity_.at(edges_.at(edge)) - flow_.at(edges_.at(edge));
  423. }
  424.  
  425. size_t FlowNetwork::GetVerticesAmount() const {
  426.     return graph_->GetVerticesAmount();
  427. }
  428.  
  429. auto FlowNetwork::ResidualNetworkView() const {
  430.     return FilteredGraph(*this, [this](const Edge &edge) {
  431.         return GetResidualCapacity(edge) > 0;
  432.     });
  433. }
  434.  
  435. FlowNetwork::FlowNetwork(int vertices) : graph_(std::make_unique<Graph>(vertices)) {
  436. }
  437.  
  438. void FlowNetworkBuilder::SetVerticeAmount(int vertices) {
  439.     flow_network_ptr_ = std::make_unique<FlowNetwork>(vertices);
  440. }
  441.  
  442. void FlowNetworkBuilder::AddEdge(int source, int destination, int capacity) {
  443.     AddEdgeInternal(source, destination, capacity);
  444.     AddEdgeInternal(destination, source, 0);
  445. }
  446.  
  447. void FlowNetworkBuilder::AddEdgeInternal(int source, int destination, int capacity) {
  448.     Edge edge(source, destination);
  449.     flow_network_ptr_->graph_->AddEdge(source, destination);
  450.     flow_network_ptr_->edges_[edge] = flow_network_ptr_->edges_.size();
  451.     SetCapacity(edge, capacity);
  452.     SetFlow(edge, 0);
  453. }
  454.  
  455. void FlowNetworkBuilder::SetCapacity(const Edge &edge, int capacity) {
  456.     SetValue(edge, capacity, &flow_network_ptr_->capacity_);
  457. }
  458.  
  459.  
  460. void FlowNetworkBuilder::SetFlow(const Edge &edge, int flow) {
  461.     SetValue(edge, flow, &flow_network_ptr_->flow_);
  462. }
  463.  
  464. void FlowNetworkBuilder::SetValue(const Edge &edge, int value, std::vector<int> *vector) {
  465.     std::size_t edge_id = flow_network_ptr_->edges_[edge];
  466.     (*vector)[edge_id] = value;
  467. }
  468.  
  469. void FlowNetworkBuilder::Reset(int source, int sink) {
  470.     flow_network_ptr_->source_ = source;
  471.     flow_network_ptr_->sink_ = sink;
  472. }
  473.  
  474. std::unique_ptr<FlowNetwork> FlowNetworkBuilder::Build() {
  475.     return std::move(flow_network_ptr_);
  476. }
  477.  
  478. void FlowNetworkBuilder::SetEdgeAmount(int edges) {
  479.     flow_network_ptr_->flow_.resize(2 * edges);
  480.     flow_network_ptr_->capacity_.resize(2 * edges);
  481. }
  482.  
  483. BfsVisitorLevel::BfsVisitorLevel(int sink, std::vector<int> *level)
  484.     : sink_(sink), level_(level) {
  485. }
  486.  
  487. bool BfsVisitorLevel::Break() {
  488.     return (*level_)[sink_] != -1;
  489. }
  490.  
  491. void BfsVisitorLevel::ExamineEdge(const Edge &edge) {
  492.     (*level_)[edge.destination] = edge.source;
  493. }
  494.  
  495. int Dinic::CalculateAugmentingFlow(int vertex, int incoming_flow) {
  496.     if (vertex == flow_network_->GetSink() || incoming_flow == 0) {
  497.         return incoming_flow;
  498.     }
  499.     int outgoing_flow = 0;
  500.     for (auto edge : flow_network_->OutgoingEdges(vertex)) {
  501.         int destination = edge.destination;
  502.         if (level_[destination] == vertex) {
  503.             auto new_incoming = std::min(incoming_flow, flow_network_->GetResidualCapacity(edge));
  504.             auto min_flow = CalculateAugmentingFlow(destination, new_incoming);
  505.             if (min_flow > 0) {
  506.                 flow_network_->ChangeFlow(edge, min_flow);
  507.                 outgoing_flow += min_flow;
  508.                 incoming_flow -= min_flow;
  509.                 if (incoming_flow == 0) {
  510.                     break;
  511.                 }
  512.             }
  513.         }
  514.     }
  515.     return outgoing_flow;
  516. }
  517.  
  518. int Dinic::MaxFlow() {
  519.     int answer = 0;
  520.     do {
  521.         level_.assign(level_.size(), -1);
  522.         auto visitor = BfsVisitorLevel(flow_network_->GetSink(), &level_);
  523.         BFS(flow_network_->GetSource(), flow_network_->ResidualNetworkView(), visitor);
  524.         if (level_[flow_network_->GetSink()] != -1) {
  525.             answer += CalculateAugmentingFlow(flow_network_->GetSource(), kInfinity);
  526.         }
  527.     } while (level_[flow_network_->GetSink()] != -1);
  528.     return answer;
  529. }
  530.  
  531. Dinic::Dinic(std::unique_ptr<FlowNetwork> flow_network)
  532.         : flow_network_(std::move(flow_network)), level_(flow_network_->GetVerticesAmount()) {}
Advertisement
Add Comment
Please, Sign In to add comment