Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <algorithm>
- #include <iostream>
- #include <numeric>
- #include <queue>
- #include <unordered_map>
- #include <utility>
- #include <vector>
- const int64_t kInfinity = 2000000000;
- struct Edge {
- int64_t vertex, capacity, flow, next;
- Edge() {}
- Edge(int64_t vertex, int64_t cap, int64_t flow, int64_t next)
- : vertex(vertex), capacity(cap), flow(flow), next(next) {}
- };
- class Graph {
- public:
- explicit Graph(int vertices, int edge_count) : vertices_(vertices), edge_count_(0),
- edges_(2 * edge_count) {}
- void Reset(int source, int sink) {
- source_ = source;
- sink_ = sink;
- head_.assign(vertices_, -1);
- }
- void AddEdge(int first_vertex, int second_vertex, int64_t cap, int64_t right_capacity) {
- edges_[edge_count_] = Edge(second_vertex, cap, 0, head_[first_vertex]);
- head_[first_vertex] = edge_count_;
- edges_[edge_count_ + 1] = Edge(first_vertex, right_capacity, 0,
- head_[second_vertex]);
- head_[second_vertex] = edge_count_ + 1;
- edge_count_ += 2;
- }
- int64_t MaxFlow() {
- int64_t max_flow = 0;
- while (BFS()) {
- current_ = head_;
- int64_t delta = DFS(source_, kInfinity);
- while (delta) {
- max_flow += delta;
- delta = DFS(source_, kInfinity);
- }
- }
- return max_flow;
- }
- bool BFS() {
- distances_.assign(vertices_, -1);
- std::queue<int> queue;
- queue.push(source_);
- distances_[source_] = 0;
- while (!queue.empty()) {
- int top = queue.front();
- queue.pop();
- for (int index = head_[top]; index != -1; index = edges_[index].next) {
- if (edges_[index].flow < edges_[index].capacity &&
- distances_[edges_[index].vertex] == -1) {
- distances_[edges_[index].vertex] = distances_[top] + 1;
- queue.push(edges_[index].vertex);
- }
- }
- }
- return distances_[sink_] != -1;
- }
- int64_t DFS(int vertex, int64_t flow) {
- if (vertex == sink_) {
- return flow;
- }
- for (int index = current_[vertex]; index >= 0; index = edges_[index].next) {
- if (edges_[index].flow < edges_[index].capacity &&
- distances_[vertex] + 1 == distances_[edges_[index].vertex]) {
- int min_flow = DFS(edges_[index].vertex,
- std::min(flow, edges_[index].capacity - edges_[index].flow));
- if (min_flow > 0) {
- edges_[index].flow += min_flow;
- edges_[index ^ 1].flow -= min_flow;
- return min_flow;
- }
- }
- }
- return 0;
- }
- private:
- int vertices_;
- int edge_count_;
- int source_;
- int sink_;
- std::vector<Edge> edges_;
- std::vector<int> head_;
- std::vector<int> distances_;
- std::vector<int> current_;
- };
- namespace std {
- template<>
- struct hash<std::pair<int, int>> {
- inline size_t operator()(const std::pair<int, int> &v) const {
- std::hash<int> int_hasher;
- return int_hasher(v.first) ^ int_hasher(v.second);
- }
- };
- }// namespace std
- int main() {
- int vertices_count, edges_count;
- std::cin >> vertices_count >> edges_count;
- std::vector<int> weights;
- for (int index = 0; index < vertices_count; ++index) {
- int current_weight;
- std::cin >> current_weight;
- weights.push_back(current_weight);
- }
- std::unordered_map<std::pair<int, int>, std::pair<int, int>> edges;
- for (int index = 0; index < edges_count; ++index) {
- int first_vertex, second_vertex;
- std::cin >> first_vertex >> second_vertex;
- if (first_vertex < second_vertex) {
- edges[std::make_pair(first_vertex, second_vertex)].first = kInfinity;
- } else {
- edges[std::make_pair(second_vertex, first_vertex)].second = kInfinity;
- }
- }
- Graph base_graph(vertices_count + 2, 2 * vertices_count +
- static_cast<int>(edges.size()));
- base_graph.Reset(0, vertices_count + 1);
- for (auto &edge : edges) {
- base_graph.AddEdge(edge.first.first, edge.first.second,
- edge.second.first, edge.second.second);
- }
- for (int index = 0; index < static_cast<int>(weights.size()); ++index) {
- base_graph.AddEdge(0, index + 1, weights[index], 0);
- }
- int left = 0;
- int right = *std::max_element(weights.begin(), weights.end());
- int64_t weights_sum = std::accumulate(weights.begin(), weights.end(), 0);
- while (right - left > 1) {
- auto middle = (left + right) / 2;
- Graph graph = base_graph;
- for (int index = 0; index < vertices_count; ++index) {
- graph.AddEdge(index + 1, vertices_count + 1, middle, 0);
- }
- if (graph.MaxFlow() == weights_sum) {
- right = middle;
- } else {
- left = middle;
- }
- }
- std::cout << right;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement