Advertisement
Guest User

Untitled

a guest
May 28th, 2018
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 16.93 KB | None | 0 0
  1. #include <algorithm>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <deque>
  5. #include <functional>
  6. #include <iostream>
  7. #include <memory>
  8. #include <queue>
  9. #include <sstream>
  10. #include <unordered_set>
  11. #include <utility>
  12. #include <vector>
  13.  
  14. template <class Iterator> class IteratorRange {
  15. public:
  16.     IteratorRange(Iterator begin, Iterator end) : begin_(begin), end_(end) {}
  17.  
  18.     Iterator begin() const { return begin_; }
  19.     Iterator end() const { return end_; }
  20.  
  21. private:
  22.     Iterator begin_, end_;
  23. };
  24.  
  25. template <typename StlIterator> class Iterator {
  26. public:
  27.     using ValueType = typename StlIterator::value_type;
  28.     using Reference = typename StlIterator::reference;
  29.  
  30.     explicit Iterator(StlIterator current) : current_(current) {}
  31.  
  32.     Iterator &operator++() {
  33.         ++current_;
  34.         return *this;
  35.     }
  36.  
  37.     bool operator==(const Iterator &rhs) const {
  38.         return current_ == rhs.current_;
  39.     }
  40.  
  41.     bool operator!=(const Iterator &rhs) const {
  42.         return current_ != rhs.current_;
  43.     }
  44.  
  45.     Reference operator*() const { return *current_; }
  46.  
  47. private:
  48.     StlIterator current_;
  49. };
  50.  
  51. template <typename SourceIterator> class ProxyIterator {
  52. public:
  53.     using ValueType = typename SourceIterator::ValueType;
  54.     using Reference = typename SourceIterator::Reference;
  55.  
  56.     explicit ProxyIterator(SourceIterator &iterator) : iterator_(iterator) {}
  57.  
  58.     ProxyIterator &operator++() {
  59.         ++iterator_;
  60.         return *this;
  61.     }
  62.  
  63.     bool operator==(const ProxyIterator &rhs) const {
  64.         return iterator_ == rhs.iterator_;
  65.     }
  66.  
  67.     bool operator!=(const ProxyIterator &rhs) const {
  68.         return iterator_ != rhs.iterator_;
  69.     }
  70.  
  71.     Reference operator*() const { return *iterator_; }
  72.  
  73. private:
  74.     SourceIterator &iterator_;
  75. };
  76.  
  77. template <typename SourceIterator> class FilterIterator {
  78. public:
  79.     using ValueType = typename SourceIterator::ValueType;
  80.     using Reference = typename SourceIterator::Reference;
  81.  
  82.     using FilterFunc = std::function<bool(const Reference)>;
  83.  
  84.     FilterIterator(SourceIterator begin, SourceIterator end, FilterFunc func)
  85.             : current_(begin), end_(end), filter_(func) {
  86.         NextIfFilter();
  87.     }
  88.  
  89.     FilterIterator(IteratorRange<SourceIterator> range, FilterFunc func)
  90.             : current_(range.begin()), end_(range.end()), filter_(func) {
  91.         NextIfFilter();
  92.     }
  93.  
  94.     FilterIterator &operator++() {
  95.         if (current_ != end_) {
  96.             ++current_;
  97.             NextIfFilter();
  98.         }
  99.         return *this;
  100.     }
  101.  
  102.     bool operator==(const FilterIterator &rhs) {
  103.         NextIfFilter();
  104.         return current_ == rhs.current_;
  105.     }
  106.  
  107.     bool operator!=(const FilterIterator &rhs) {
  108.         return !(*this == rhs);
  109.     }
  110.  
  111.     void NextIfFilter() {
  112.         while (current_ != end_ && filter_(*current_)) {
  113.             ++current_;
  114.         }
  115.     }
  116.  
  117.     Reference operator*() {
  118.         NextIfFilter();
  119.         return *current_;
  120.     }
  121.  
  122. private:
  123.     SourceIterator current_;
  124.     SourceIterator end_;
  125.     FilterFunc filter_;
  126. };
  127.  
  128. class Graph {
  129. public:
  130.     struct Edge {
  131.         int from;
  132.         int to;
  133.         int id;
  134.     };
  135.  
  136.     using EdgeIterator = Iterator<std::vector<Edge>::const_iterator>;
  137.  
  138.     explicit Graph(int vertex_count) : outgoing_edges_(vertex_count) {}
  139.  
  140.     auto OutgoingEdges(int vertex) const {
  141.         return IteratorRange<EdgeIterator>(
  142.                 EdgeIterator(outgoing_edges_[vertex].cbegin()),
  143.                 EdgeIterator(outgoing_edges_[vertex].cend()));
  144.     }
  145.  
  146.     int VertexCount() const { return outgoing_edges_.size(); }
  147.  
  148.     const Edge &AddEdge(int from, int to) {
  149.         outgoing_edges_[from].push_back(Edge{from, to, edge_count_++});
  150.         return outgoing_edges_[from].back();
  151.     }
  152.  
  153. private:
  154.     int edge_count_ = 0;
  155.     std::vector<std::vector<Edge>> outgoing_edges_;
  156. };
  157.  
  158. template <typename Graph> class LevelGraph {
  159. public:
  160.     using Edge = typename Graph::Edge;
  161.     using InnerEdgeIterator = FilterIterator<typename Graph::EdgeIterator>;
  162.     using EdgeIterator = ProxyIterator<InnerEdgeIterator>;
  163.  
  164.     LevelGraph(const Graph &graph, const std::vector<int> &distances)
  165.             : dist_(distances) {
  166.         auto filter_func = [this](const Edge &edge) {
  167.             return dist_[edge.to] != dist_[edge.from] + 1;
  168.         };
  169.  
  170.         for (int vertex = 0; vertex < graph.VertexCount(); ++vertex) {
  171.             outgoing_edges_.emplace_back(
  172.                     InnerEdgeIterator(graph.OutgoingEdges(vertex), filter_func),
  173.                     InnerEdgeIterator(graph.OutgoingEdges(vertex).end(),
  174.                                       graph.OutgoingEdges(vertex).end(), filter_func));
  175.         }
  176.     }
  177.  
  178.     IteratorRange<EdgeIterator> OutgoingEdges(int vertex) {
  179.         outgoing_edges_[vertex].first.NextIfFilter();
  180.         return IteratorRange<EdgeIterator>(
  181.                 EdgeIterator(outgoing_edges_[vertex].first),
  182.                 EdgeIterator(outgoing_edges_[vertex].second));
  183.     }
  184.  
  185.     int VertexCount() const { return outgoing_edges_.size(); }
  186.  
  187.     bool is_terminal_reachable(int vertex) { return dist_[vertex] != -1; }
  188.  
  189. private:
  190.     std::vector<int> dist_;
  191.     std::vector<std::pair<InnerEdgeIterator, InnerEdgeIterator>> outgoing_edges_;
  192. };
  193.  
  194. template <typename Graph, typename Visitor>
  195. void BreadthFirstSearch(int start_vertex, const Graph &graph, Visitor visitor) {
  196.     std::unordered_set<int> used;
  197.     std::queue<int> unvisited_vertices;
  198.  
  199.     unvisited_vertices.push(start_vertex);
  200.     used.insert(start_vertex);
  201.     visitor.DiscoverVertex(start_vertex);
  202.  
  203.     while (!unvisited_vertices.empty()) {
  204.         auto from = unvisited_vertices.front();
  205.         unvisited_vertices.pop();
  206.         visitor.ExamineVertex(from);
  207.         for (auto edge : graph.OutgoingEdges(from)) {
  208.             if (!used.count(edge.to)) {
  209.                 visitor.DiscoverVertex(edge.to);
  210.                 unvisited_vertices.push(edge.to);
  211.                 used.insert(edge.to);
  212.                 visitor.ExamineEdge(edge);
  213.             }
  214.         }
  215.     }
  216. }
  217.  
  218. template <typename Graph, typename Visitor>
  219. void DepthFirstSearchImpl(int vertex, Graph &graph, Visitor &visitor,
  220.                           std::vector<bool> &used) {
  221.     visitor.DiscoverVertex(vertex);
  222.     if (visitor.CanStop()) {
  223.         return;
  224.     }
  225.  
  226.     used[vertex] = true;
  227.  
  228.     for (auto edge : graph.OutgoingEdges(vertex)) {
  229.         if (!used[edge.to]) {
  230.             visitor.ExamineEdge(edge);
  231.             DepthFirstSearchImpl(edge.to, graph, visitor, used);
  232.             if (visitor.CanStop()) {
  233.                 return;
  234.             }
  235.  
  236.             visitor.FinishEdge(edge);
  237.         }
  238.     }
  239.  
  240.     visitor.FinishVertex(vertex);
  241. }
  242.  
  243. template <typename Graph, typename Visitor>
  244. void DepthFirstSearch(int start_vertex, Graph &graph, Visitor visitor) {
  245.     std::vector<bool> used(graph.VertexCount());
  246.     DepthFirstSearchImpl(start_vertex, graph, visitor, used);
  247. }
  248.  
  249. template <typename SourceGraph> class FilteredGraph {
  250. public:
  251.     using EdgeIterator = FilterIterator<typename SourceGraph::EdgeIterator>;
  252.     using FilterFunc = std::function<bool(const typename SourceGraph::Edge &)>;
  253.     using Edge = typename SourceGraph::Edge;
  254.  
  255.     FilteredGraph(std::shared_ptr<const SourceGraph> source_graph,
  256.                   FilterFunc func)
  257.             : source_graph_(source_graph), has_edge_(func) {}
  258.  
  259.     auto OutgoingEdges(int vertex) const {
  260.         return IteratorRange<EdgeIterator>(
  261.                 EdgeIterator(source_graph_->OutgoingEdges(vertex), has_edge_),
  262.                 EdgeIterator(source_graph_->OutgoingEdges(vertex).end(),
  263.                              source_graph_->OutgoingEdges(vertex).end(), has_edge_)
  264.  
  265.         );
  266.     }
  267.  
  268.     int VertexCount() const { return source_graph_->VertexCount(); }
  269.  
  270. private:
  271.     std::shared_ptr<const SourceGraph> source_graph_;
  272.     FilterFunc has_edge_;
  273. };
  274.  
  275. class FlowNetwork {
  276. public:
  277.     using Edge = typename Graph::Edge;
  278.  
  279.     static const int INF = 1000000000;
  280.  
  281.     struct EdgeProperties {
  282.         int flow;
  283.         int cap;
  284.         int opposite_index;
  285.     };
  286.  
  287.     explicit FlowNetwork(int vertex_count)
  288.             : network_(std::make_shared<Graph>(vertex_count)) {}
  289.  
  290.     Edge AddEdge(int from, int to, int cap) {
  291.         auto &edge = network_->AddEdge(from, to);
  292.         auto &back_edge = network_->AddEdge(to, from);
  293.  
  294.         edge_properties_.push_back({0, cap, back_edge.id});
  295.         edge_properties_.push_back({0, 0, edge.id});
  296.  
  297.         return edge;
  298.     }
  299.  
  300.     void IncFlow(const Edge &edge, int flow) {
  301.         auto &edge_props = edge_properties_[edge.id];
  302.         edge_properties_[edge.id].flow += flow;
  303.         edge_properties_[edge_props.opposite_index].flow -= flow;
  304.     }
  305.  
  306.     void SetCapacity(const Edge &edge, int capacity) {
  307.         edge_properties_[edge.id].cap = capacity;
  308.     }
  309.  
  310.     void ClearFlow() {
  311.         for (auto &props : edge_properties_) {
  312.             props.flow = 0;
  313.         }
  314.     }
  315.  
  316.     int ResidualCapacity(const Edge &edge) const {
  317.         auto &props = edge_properties_[edge.id];
  318.         return props.cap - props.flow;
  319.     }
  320.  
  321.     bool IsInResidualNetwork(const Edge &edge) const {
  322.         int res_cap = ResidualCapacity(edge);
  323.         return res_cap > 0;
  324.     }
  325.  
  326.     FilteredGraph<Graph> ResidualNetwork() const {
  327.         auto filter_func = [this](const Edge &edge) {
  328.             return !IsInResidualNetwork(edge);
  329.         };
  330.  
  331.         return FilteredGraph<Graph>(network_, filter_func);
  332.     }
  333.  
  334.     int64_t CalcFlowValue() {
  335.         int64_t flow = 0;
  336.         for (auto edge : network_->OutgoingEdges(0)) {
  337.             auto &edge_props = edge_properties_[edge.id];
  338.             flow += edge_props.flow;
  339.         }
  340.  
  341.         return flow;
  342.     }
  343.  
  344. private:
  345.     std::shared_ptr<Graph> network_;
  346.     std::vector<EdgeProperties> edge_properties_;
  347. };
  348.  
  349. template <typename VisitorState> class BreadthFirstSearchVisitor {
  350. public:
  351.     explicit BreadthFirstSearchVisitor(VisitorState &state) : state_(state) {}
  352.  
  353.     void ExamineEdge(const typename VisitorState::Graph::Edge &edge) {
  354.         state_.ExamineEdge(edge);
  355.     }
  356.  
  357.     void ExamineVertex(int vertex) { state_.ExamineVertex(vertex); }
  358.  
  359.     void DiscoverVertex(int vertex) { state_.DiscoverVertex(vertex); }
  360.  
  361. private:
  362.     VisitorState &state_;
  363. };
  364.  
  365. template <typename VisitorState>
  366. auto MakeBreadthFirstSearchVisitor(VisitorState &state) {
  367.     return BreadthFirstSearchVisitor<VisitorState>(state);
  368. }
  369.  
  370. template <typename SourceGraph> class CalcDistVisitorState {
  371. public:
  372.     using Graph = SourceGraph;
  373.  
  374.     explicit CalcDistVisitorState(const Graph &graph)
  375.             : dist_(graph.VertexCount(), -1) {}
  376.  
  377.     void ExamineEdge(const typename Graph::Edge &edge) {
  378.         dist_[edge.to] = dist_[edge.from] + 1;
  379.     }
  380.  
  381.     void DiscoverVertex(int vert) { dist_[vert] = 0; }
  382.  
  383.     void ExamineVertex(int vert) {}
  384.  
  385.     const std::vector<int> &GetDistances() const { return dist_; }
  386.  
  387. private:
  388.     std::vector<int> dist_;
  389. };
  390.  
  391. template <typename Graph> LevelGraph<Graph> MakeLevelGraph(const Graph &graph) {
  392.     CalcDistVisitorState<Graph> distance_visitor(graph);
  393.     BreadthFirstSearch(0, graph, MakeBreadthFirstSearchVisitor(distance_visitor));
  394.     LevelGraph<Graph> res(graph, distance_visitor.GetDistances());
  395.     return res;
  396. }
  397.  
  398. template <typename VisitorState> class DepthFirstSearchVisitor {
  399. public:
  400.     explicit DepthFirstSearchVisitor(VisitorState &state) : state_(state) {}
  401.  
  402.     void ExamineEdge(const typename VisitorState::Graph::Edge &edge) {
  403.         state_.ExamineEdge(edge);
  404.     }
  405.  
  406.     void FinishEdge(const typename VisitorState::Graph::Edge &edge) {
  407.         state_.FinishEdge(edge);
  408.     }
  409.  
  410.     void FinishVertex(int vertex) { state_.FinishVertex(vertex); }
  411.  
  412.     void DiscoverVertex(int vertex) { state_.DiscoverVertex(vertex); }
  413.  
  414.     bool CanStop() { return state_.CanStop(); }
  415.  
  416. private:
  417.     VisitorState &state_;
  418. };
  419.  
  420. template <typename VisitorState>
  421. auto MakeDepthFirstSearchVisitor(VisitorState &state) {
  422.     return DepthFirstSearchVisitor<VisitorState>(state);
  423. }
  424.  
  425. template <typename LevelGraph> class BlockFlowVisitorState {
  426. public:
  427.     using Graph = LevelGraph;
  428.  
  429.     BlockFlowVisitorState(LevelGraph &level_graph, FlowNetwork &network,
  430.                           int terminal_vertex)
  431.             : level_graph_(level_graph), network_(network),
  432.               terminal_vertex_(terminal_vertex) {}
  433.  
  434.     void ExamineEdge(const typename Graph::Edge &edge) {
  435.         cur_path_.push_back(edge);
  436.     }
  437.  
  438.     void FinishEdge(const typename Graph::Edge &edge) { cur_path_.pop_back(); }
  439.  
  440.     const int INF = 1000000000;
  441.     void DiscoverVertex(int vertex) {
  442.         if (vertex == terminal_vertex_) {
  443.             can_stop_ = true;
  444.  
  445.             int flow = INF;
  446.             for (auto &edge : cur_path_) {
  447.                 flow = std::min(flow, network_.ResidualCapacity(edge));
  448.             }
  449.  
  450.             for (auto &edge : cur_path_) {
  451.                 network_.IncFlow(edge, flow);
  452.             }
  453.  
  454.             cur_path_.clear();
  455.         }
  456.     }
  457.  
  458.     void FinishVertex(int vertex) {}
  459.  
  460.     bool CanStop() const { return can_stop_; }
  461.  
  462.     bool ReachedTerminal() const { return CanStop(); }
  463.  
  464. private:
  465.     LevelGraph &level_graph_;
  466.     FlowNetwork &network_;
  467.     int terminal_vertex_;
  468.     std::deque<typename Graph::Edge> cur_path_;
  469.     bool can_stop_ = false;
  470. };
  471.  
  472. int64_t FindMaxFlow(FlowNetwork &network) {
  473.     bool is_terminal_reachable = true;
  474.     while (is_terminal_reachable) {
  475.         auto level_graph = MakeLevelGraph(network.ResidualNetwork());
  476.         int terminal_vertex = level_graph.VertexCount() - 1;
  477.  
  478.         is_terminal_reachable = level_graph.is_terminal_reachable(terminal_vertex);
  479.  
  480.         if (is_terminal_reachable) {
  481.             bool reached_terminal = true;
  482.             while (reached_terminal) {
  483.                 BlockFlowVisitorState<decltype(level_graph)> block_flow_calculator(
  484.                         level_graph, network, terminal_vertex);
  485.                 DepthFirstSearch(0, level_graph,
  486.                                  MakeDepthFirstSearchVisitor(block_flow_calculator));
  487.                 reached_terminal = block_flow_calculator.ReachedTerminal();
  488.             }
  489.         }
  490.     }
  491.  
  492.     return network.CalcFlowValue();
  493. }
  494.  
  495. // returns the minimal value (between begin and end), for which the predicate is
  496. // true
  497. template <typename Predicate>
  498. int FindMinimalTrue(int begin, int end, Predicate predicate) {
  499.     while (begin != end) {
  500.         int mid = (begin + end) / 2;
  501.  
  502.         if (predicate(mid)) {
  503.             end = mid;
  504.         } else {
  505.             begin = mid + 1;
  506.         }
  507.     }
  508.  
  509.     return end;
  510. }
  511.  
  512. void Read(std::vector<int> &starting_gold_bars_amount,
  513.           std::vector<std::vector<int>> &trust_graph) {
  514.     int people, trust_pairs;
  515.     std::cin >> people >> trust_pairs;
  516.     starting_gold_bars_amount.resize(people);
  517.     for (auto &bars_amount : starting_gold_bars_amount) {
  518.         std::cin >> bars_amount;
  519.     }
  520.  
  521.     trust_graph.resize(people + 1);
  522.     for (int i = 0; i < trust_pairs; ++i) {
  523.         int from, to;
  524.         std::cin >> from >> to;
  525.         trust_graph[from].push_back(to);
  526.     }
  527. }
  528.  
  529. FlowNetwork
  530. BuildFlowNetwork(const std::vector<int> &starting_gold_bars_amount,
  531.                  const std::vector<std::vector<int>> &trust_graph,
  532.                  std::vector<typename FlowNetwork::Edge> &sink_edges,
  533.                  int &total_gold_bars) {
  534.  
  535.     int people = static_cast<int>(starting_gold_bars_amount.size());
  536.     FlowNetwork network(people + 2);
  537.     for (int i = 0; i < people; ++i) {
  538.         network.AddEdge(0, i + 1, starting_gold_bars_amount[i]);
  539.         sink_edges.push_back(network.AddEdge(i + 1, people + 1, 0));
  540.         total_gold_bars += starting_gold_bars_amount[i];
  541.     }
  542.  
  543.     for (int from = 1; from <= people; ++from) {
  544.         for (auto to : trust_graph[from]) {
  545.             network.AddEdge(from, to, FlowNetwork::INF);
  546.         }
  547.     }
  548.     return network;
  549. }
  550.  
  551. int FindMinimalGoldBarsAmount(
  552.         std::vector<typename FlowNetwork::Edge> &sink_edges, FlowNetwork &network,
  553.         int total_gold_bars) {
  554.     auto check_enough_flow_with_capacity = [&network, &sink_edges,
  555.             total_gold_bars](int cap) {
  556.         network.ClearFlow();
  557.         for (auto &edge : sink_edges) {
  558.             network.SetCapacity(edge, cap);
  559.         }
  560.  
  561.         int64_t flow = FindMaxFlow(network);
  562.         return flow == total_gold_bars;
  563.     };
  564.  
  565.     return FindMinimalTrue(0, total_gold_bars, check_enough_flow_with_capacity);
  566. }
  567.  
  568. int main() {
  569.     std::vector<int> starting_gold_bars_amount;
  570.     std::vector<std::vector<int>> trust_graph;
  571.     Read(starting_gold_bars_amount, trust_graph);
  572.  
  573.     int total_gold_bars = 0;
  574.     std::vector<typename FlowNetwork::Edge> sink_edges;
  575.     FlowNetwork network = BuildFlowNetwork(starting_gold_bars_amount, trust_graph,
  576.                                            sink_edges, total_gold_bars);
  577.  
  578.     std::cout << FindMinimalGoldBarsAmount(sink_edges, network, total_gold_bars)
  579.               << std::endl;
  580. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement