mfgnik

Untitled

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