Problem:
K:  AOR イカちゃんの成績
問題
AOR イカちゃんは $N$ 回のレポートの点数のみで成績が決まる授業を受けている。

 AOR イカちゃんは同じ授業を受けている友達が $M$ 人いて、自分が苦手なテーマのレポートは、そのテーマが得意な友達のレポートを写すことで、その友達と同じ点数を取ることができる。

ただし、他人のレポートを写していることを先生に気付かれてはいけないので、 $N$ 回のうち少なくとも $K$ 回は他人のレポートを写さず、自力でレポートを仕上げなくてはならない。
また、 AOR イカちゃんは友達に迷惑をかけたくないと思ったので友達 $i$ に対してレポートを写すのは $T_i$ 回以下にすることにした。

 AOR イカちゃんが自力でレポートを仕上げたときの点数と、友達がレポートを仕上げた時の点数が与えられたときに、 AOR イカちゃんが取ることのできる合計点数の最大値を答えよ。
制約
$1 \le N \le 100$
$0 \le M \le 100$
$0 \le K \le N$
$0 \le a_i \le 100$
$0 \le b_{ij} \le 100$
$0 \le T_i \le N$
入力
入力は以下の形式で標準入力から与えられる。
$N \ M \ K$
$a_1 \ \cdots \ a_N$
$b_{11} \ \cdots \ b_{1N}$
$\vdots$
$b_{M1} \ \cdots \ b_{MN}$
$T_1 \ \cdots \ T_M$
$a_i$ はAORイカちゃんが $i$ 番目のレポートを仕上げた時の点数を、$b_{ij}$ は友達 $i$ が $j$ 番目のレポートを仕上げた時の点数を表す。
出力
AOR イカちゃんが取ることのできる合計点数の最大値を出力せよ。また、末尾に改行も出力せよ。
サンプル
入力例 1
3 2 2
50 65 70
80 100 80
90 65 45
1 1
出力例 1
225
AOR イカちゃんは 1 回だけ他人のレポートを写すことができるので、友達 2 の 1 つめのレポートを写すことで、 AOR イカちゃんは最高点数を取ることができる。
入力例 2
3 0 3
0 0 0
出力例 2
0
AOR イカちゃんには友達がいないため、レポートを写すことはできない。

Submitted solutions:

code_snippet: #line 1 "test/aizu-online-judge/2815.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/2815"

#include <iostream>

#line 2 "src/graph/directed/flow/min_cost_flow.hpp"

/**
 * @file min_cost_flow.hpp
 * @brief Minimum Cost Flow
 * @date 2021-01-15
 *
 *
 */

#include <algorithm>
#include <optional>
#include <queue>

#line 2 "src/graph/directed/flow/base.hpp"

/**
 * @file base.hpp
 * @brief Flow Graph
 * @date 2021-01-15
 *
 *
 */

#include <cassert>
#include <numeric>
#include <vector>

namespace workspace {

template <class Cap, class Cost = void> class flow_graph {
 protected:
  class adjacency_impl;

 public:
  using container_type = std::vector<adjacency_impl>;
  using size_type = typename container_type::size_type;

  class unweighted_edge {
   public:
    size_type src, dst;
    Cap cap;

    unweighted_edge() = default;

    unweighted_edge(size_type src, size_type dst, const Cap &cap)
        : src(src), dst(dst), cap(cap) {
      assert(!(cap < static_cast<Cap>(0)));
    }

    template <class Os>
    friend Os &operator<<(Os &__os, unweighted_edge const &__e) {
      return __os << __e.src << " " << __e.dst << " " << __e.cap;
    }

   protected:
    unweighted_edge make_rev() { return {dst, src, 0}; }
  };

  class weighted_edge : public unweighted_edge {
   public:
    Cost cost;

    weighted_edge() = default;

    weighted_edge(size_type src, size_type dst, const Cap &cap,
                  const Cost &cost)
        : unweighted_edge(src, dst, cap), cost(cost) {}

    template <class Os>
    friend Os &operator<<(Os &__os, weighted_edge const &__e) {
      return __os << static_cast<unweighted_edge>(__e) << " " << __e.cost;
    }

   protected:
    weighted_edge make_rev() {
      return {unweighted_edge::dst, unweighted_edge::src, 0, -cost};
    }
  };

  using edge = typename std::conditional<std::is_void<Cost>::value,
                                         unweighted_edge, weighted_edge>::type;

 protected:
  struct edge_impl : edge {
    bool aux = false;
    edge_impl *rev = nullptr;

    edge_impl() = default;

    edge_impl(const edge_impl &__e) = default;

    edge_impl(const edge &__e) : edge(__e) {}

    void flow(const Cap &f) { edge::cap -= f, rev->cap += f; }

    edge_impl rev_cp() {
      edge_impl __e;
      if (rev)
        __e = *rev;
      else {
        __e = edge::make_rev();
        __e.aux = true;
      }
      __e.rev = this;
      return __e;
    }
  };

 public:
  class adjacency {
   public:
    using value_type = edge;
    using reference = edge &;
    using const_reference = edge const &;
    using pointer = edge *;
    using const_pointer = const edge *;

    class const_iterator {
     public:
      const edge_impl *__p;

      bool operator!=(const_iterator const &__x) const {
        return __p != __x.__p;
      }

      const_iterator &operator++() {
        do
          ++__p;
        while (__p->rev && __p->aux);
        return *this;
      }

      const_pointer operator->() const { return __p; }

      const_reference operator*() const { return *__p; }
    };

    adjacency()
        : first(new edge_impl[2]), last(first + 1), __s(first), __t(first) {}

    ~adjacency() { delete[] first; }

    const_reference operator[](size_type i) const {
      assert(i < size());
      return *(first + i);
    }

    size_type size() const { return __t - first; }

    auto begin() const { return const_iterator{__s}; }
    auto end() const { return const_iterator{__t}; }

    /**
     * @brief Construct a new adjacency object
     *
     * @param __x Rvalue reference to another object
     */
    adjacency(adjacency &&__x) : first(nullptr) { operator=(std::move(__x)); }

    /**
     * @brief Assignment operator.
     *
     * @param __x Rvalue reference to another object
     * @return Reference to this object.
     */
    adjacency &operator=(adjacency &&__x) {
      std::swap(first, __x.first);
      last = __x.last;
      __s = __x.__s;
      __t = __x.__t;
      return *this;
    }

   protected:
    edge_impl *first, *last, *__s, *__t;
  };

  using value_type = adjacency;
  using reference = adjacency &;
  using const_reference = adjacency const &;

 protected:
  class adjacency_impl : public adjacency {
   public:
    using base = adjacency;
    using base::__s;
    using base::__t;
    using base::first;
    using base::last;

    template <class... Args> auto emplace(Args &&... args) {
      if (__t == last) {
        size_type __n(last - first);
        edge_impl *loc = new edge_impl[__n << 1 | 1];
        __s += loc - first;
        __t = loc;
        for (edge_impl *__p{first}; __p != last; ++__p, ++__t)
          __p->rev->rev = __t, *__t = *__p;
        delete[] first;
        first = loc;
        last = __t + __n;
      }
      *__t = edge_impl(args...);
      if (__s->aux) ++__s;
      return __t++;
    }

    using iterator = edge_impl *;
    auto begin() const { return first; }
    auto end() const { return __t; }
  };

 public:
  /**
   * @brief Construct a new flow graph object
   *
   * @param __n Number of vertices
   */
  flow_graph(size_type __n = 0) : graph(__n) {}

  /**
   * @brief Construct a new flow graph object
   *
   * @param __x Const reference to another object
   */
  flow_graph(const flow_graph &__x) : graph(__x.size()) {
    for (auto &&__adj : __x)
      for (auto &&__e : __adj) _add_edge(__e);
  }

  /**
   * @brief Assignment operator.
   *
   * @param __x Rvalue reference to another object
   * @return Reference to this object.
   */
  flow_graph &operator=(flow_graph &&__x) {
    graph.swap(__x.graph);
    return *this;
  }

  /**
   * @return Number of nodes.
   */
  size_type size() const { return graph.size(); }

  reference operator[](size_type node) {
    assert(node < size());
    return graph[node];
  }

  const_reference &operator[](size_type node) const {
    assert(node < size());
    return graph[node];
  }

  class const_iterator : public container_type::const_iterator {
   public:
    using base = typename container_type::const_iterator;
    using const_reference = const adjacency &;
    using const_pointer = const adjacency *;

    const_iterator(base const &__i) : base(__i) {}

    const_pointer operator->() const { return base::operator->(); }

    const_reference operator*() const { return base::operator*(); }
  };

  auto begin() const { return const_iterator{graph.begin()}; }
  auto end() const { return const_iterator{graph.end()}; }

  size_type add_node() { return add_nodes(1).front(); }

  virtual std::vector<size_type> add_nodes(size_type __n) {
    std::vector<size_type> __nds(__n);
    std::iota(__nds.begin(), __nds.end(), graph.size());
    __n += graph.size();
    if (__n > graph.capacity()) {
      flow_graph __x(__n);
      for (auto &&adj : graph)
        for (auto &&__e : adj)
          if (!__e.aux) __x._add_edge(__e);
      graph.swap(__x.graph);
    } else
      graph.resize(__n);
    return __nds;
  }

  template <class... Args> const edge &add_edge(Args &&... args) {
    return *_add_edge(edge(args...));
  }

 protected:
  template <class... Args> edge_impl *_add_edge(Args &&... args) {
    edge_impl __e(args...);
    assert(__e.src < size());
    assert(__e.dst < size());
    auto __p = graph[__e.src].emplace(__e);
    __p->rev = graph[__e.dst].emplace(__p->rev_cp());
    return __p;
  }

  constexpr static size_type nil = -1;
  container_type graph;

  template <class Os> friend Os &operator<<(Os &__os, flow_graph const &__g) {
    for (const auto &adj : __g)
      for (const auto &e : adj) __os << e << "\n";
    return __os;
  }
};

}  // namespace workspace
#line 16 "src/graph/directed/flow/min_cost_flow.hpp"

namespace workspace {

/**
 * @brief Successive Shortest Path Algorithm.
 *
 * @tparam Cap Capacity type
 * @tparam Cost Cost type
 * @tparam Density_tag Whether the graph is dense.
 */
template <class Cap, class Cost = Cap, bool Density_tag = false>
class min_cost_flow : public flow_graph<Cap, Cost> {
  using base = flow_graph<Cap, Cost>;
  using edge_impl = typename base::edge_impl;
  using base::nil;

 public:
  using size_type = typename base::size_type;
  using base::size;

  /**
   * @brief Construct a new min_cost_flow object
   *
   * @param __n Number of vertices
   */
  min_cost_flow(size_type __n = 0)
      : base::flow_graph(__n), current(0), abs_sum(0), b(__n), p(__n) {}

  std::vector<size_type> add_nodes(size_type __n) override {
    auto __nds = base::add_nodes(__n);
    b.resize(size());
    p.resize(size());
    return __nds;
  }

  /**
   * @brief Add an edge with a unit capacity to the graph.
   *
   * @param src Source
   * @param dst Destination
   * @param cost Cost
   * @return Reference to the edge.
   */
  auto &add_edge(size_type src, size_type dst, const Cost &cost) {
    return add_edge(src, dst, 1, cost);
  }

  /**
   * @brief Add an edge to the graph.
   *
   * @param src Source
   * @param dst Destination
   * @param cap Capacity
   * @param cost Cost
   * @return Reference to the edge.
   */
  typename base::edge const &add_edge(size_type src, size_type dst,
                                      const Cap &cap, const Cost &cost) {
    edge_impl *__p = base::_add_edge(typename base::edge(src, dst, cap, cost));
    if (cost < static_cast<Cost>(0)) {
      __p->flow(cap);
      b[src] -= cap;
      b[dst] += cap;
      current += cap * cost;
      abs_sum -= cap * cost;
    } else
      abs_sum += cap * cost;
    return *__p;
  }

  /**
   * @brief Add an edge to the graph.
   *
   * @param src Source
   * @param dst Destination
   * @param lower Lower bound of flow
   * @param upper Upper bound of flow
   * @param cost Cost
   * @return Reference to the edge.
   */
  auto &add_edge(size_type src, size_type dst, const Cap &lower,
                 const Cap &upper, const Cost &cost) {
    assert(!(upper < lower));
    b[src] -= lower;
    b[dst] += lower;
    current += lower * cost;
    return add_edge(src, dst, upper - lower, cost);
  }

  /**
   * @brief Increase the balance of a node.
   *
   * @param node
   * @param vol Default: 1
   */
  void supply(size_type node, const Cap &vol = 1) {
    assert(node < size());
    b[node] += vol;
  }

  /**
   * @brief Decrease the balance of a node.
   *
   * @param node
   * @param vol Default: 1
   */
  void demand(size_type node, const Cap &vol = 1) {
    assert(node < size());
    b[node] -= vol;
  }

  /**
   * @param node
   * @return Balance of the node
   */
  Cap balance(size_type node) { return b[node]; }

  /**
   * @return Cost of current flow.
   */
  Cost cost() const { return current; }

  /**
   * @brief Run Successive Shortest Path Algorithm.
   *
   * @return Whether a balanced flow exists.
   */
  bool flow() {
    for (bool aug = true; aug;) {
      aug = false;
      std::vector<edge_impl *> last(size());
      Dijkstra(last);
      std::vector<bool> shut(size());
      for (size_type dst{}; dst != size(); ++dst) {
        if (b[dst] < static_cast<Cap>(0) && last[dst]) {
          Cap resid{-b[dst]};
          size_type src{dst}, block{nil};
          while (last[src] && !shut[src]) {
            if (!(resid < last[src]->cap)) resid = last[block = src]->cap;
            src = last[src]->src;
          }
          if (shut[src])
            block = src;
          else {
            if (!(resid < b[src])) resid = b[block = src];
            for (edge_impl *e{last[dst]}; e; e = last[e->src]) {
              e->cap -= resid;
              e->rev->cap += resid;
            }
            b[src] -= resid;
            b[dst] += resid;
            current += p[dst] * resid;
            aug = true;
          }
          if (block != nil)
            for (size_type node{dst};; node = last[node]->src) {
              shut[node] = true;
              if (node == block) break;
            }
        }
      }
    }
    return std::none_of(begin(b), end(b), [](const Cap &s) {
      return s < static_cast<Cap>(0) || static_cast<Cap>(0) < s;
    });
  }

 protected:
  Cost current, abs_sum;
  std::vector<Cap> b;
  std::vector<Cost> p;

  void Dijkstra(std::vector<edge_impl *> &last) {
    const Cost infty(abs_sum + 1);
    std::vector<Cost> newp(size(), infty);

    if constexpr (Density_tag) {  // O(V^2)
      std::vector<bool> used(size());

      for (size_type src{}; src != size(); ++src)
        if (static_cast<Cap>(0) < b[src]) {
          used[src] = true;
          newp[src] = 0;

          for (auto &e : base::graph[src])
            if (!(static_cast<Cap>(0) < b[e.dst]) &&
                static_cast<Cap>(0) < e.cap && newp[e.dst] > e.cost)
              newp[e.dst] = e.cost, last[e.dst] = &e;
        }

      for (;;) {
        size_type src{nil};
        Cost sp{infty};

        for (size_type node{}; node != size(); ++node) {
          if (used[node] || newp[node] == infty) continue;
          if (Cost __d = newp[node] - p[node]; __d < sp) sp = __d, src = node;
        }

        if (src == nil) break;
        used[src] = true;

        for (auto &e : base::graph[src])
          if (static_cast<Cap>(0) < e.cap && newp[src] + e.cost < newp[e.dst]) {
            newp[e.dst] = newp[src] + e.cost;
            last[e.dst] = &e;
          }
      }
    }

    else {  // O((V + E)logV)
      struct sp_node {
        size_type id;
        Cost __d;
        sp_node(size_type id, Cost __d) : id(id), __d(__d) {}
        bool operator<(const sp_node &rhs) const { return rhs.__d < __d; }
      };

      std::priority_queue<sp_node> __q;
      for (size_type src{}; src != size(); ++src)
        if (b[src] > static_cast<Cap>(0)) {
          newp[src] = 0;
          for (auto &e : base::graph[src])
            if (static_cast<Cap>(0) < e.cap && newp[e.dst] > e.cost) {
              __q.emplace(e.dst, (newp[e.dst] = e.cost) - p[e.dst]);
              last[e.dst] = &e;
            }
        }

      while (!__q.empty()) {
        auto [src, __d] = __q.top();
        __q.pop();
        if (__d + p[src] != newp[src]) continue;
        for (auto &e : base::graph[src])
          if (auto __d = newp[src] + e.cost;
              static_cast<Cap>(0) < e.cap && __d < newp[e.dst]) {
            __q.emplace(e.dst, (newp[e.dst] = __d) - p[e.dst]);
            last[e.dst] = &e;
          }
      }
    }

    p.swap(newp);
  }
};

template <class Cap, class Gain = Cap, bool Density_tag = false>
class max_gain_flow : public min_cost_flow<Cap, Gain, Density_tag> {
  using base = min_cost_flow<Cap, Gain, Density_tag>;
  using base::cost;

 public:
  using base::min_cost_flow;
  using size_type = typename base::size_type;

  /**
   * @brief Add an edge with a unit capacity to the graph.
   *
   * @param src Source
   * @param dst Destination
   * @param gain Gain
   * @return Reference to the edge.
   */
  auto &add_edge(size_type src, size_type dst, const Gain &gain) {
    return add_edge(src, dst, 1, gain);
  }

  /**
   * @brief Add an edge to the graph.
   *
   * @param src Source
   * @param dst Destination
   * @param cap Capacity
   * @param gain Gain
   * @return Reference to the edge.
   */
  auto &add_edge(size_type src, size_type dst, const Cap &cap,
                 const Gain &gain) {
    return base::add_edge(src, dst, cap, -gain);
  }

  /**
   * @brief Add an edge to the graph.
   *
   * @param src Source
   * @param dst Destination
   * @param lower Lower bound of flow
   * @param upper Upper bound of flow
   * @param gain Gain
   * @return Reference to the edge.
   */
  auto &add_edge(size_type src, size_type dst, const Cap &lower,
                 const Cap &upper, const Gain &gain) {
    return base::add_edge(src, dst, lower, upper, -gain);
  }

  /**
   * @return Gain of current flow.
   */
  Gain gain() const { return -base::current; }
};

}  // namespace workspace
#line 6 "test/aizu-online-judge/2815.test.cpp"

int main() {
  using namespace workspace;

  int n, m, k;
  std::cin >> n >> m >> k;

  min_cost_flow<int, int, 1> mcf;
  const auto dst = mcf.add_node();
  const auto dst2 = mcf.add_node();
  const auto dst3 = mcf.add_node();

  mcf.demand(dst, n);
  mcf.add_edge(dst2, dst, n, 0);
  mcf.add_edge(dst3, dst, n - k, 0);

  const auto r = mcf.add_nodes(n);
  for (auto u : r) {
    mcf.supply(u);
    std::cin >> k;
    mcf.add_edge(u, dst2, -k);
  }

  const auto f = mcf.add_nodes(m);
  for (auto v : f) {
    for (auto u : r) {
      std::cin >> k;
      mcf.add_edge(u, v, -k);
    }
  }

  for (auto v : f) {
    std::cin >> k;
    mcf.add_edge(v, dst3, k, 0);
  }

  assert(mcf.flow());
  std::cout << -mcf.cost() << "\n";
}
accuracy: 1
time_ms: 10
memory_kb: 4180
final_rank: 7

code_snippet: #line 1 "test/aizu-online-judge/2815.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/2815"

#include <iostream>

#line 2 "src/graph/directed/flow/min_cost_flow.hpp"

/**
 * @file min_cost_flow.hpp
 * @brief Minimum Cost Flow
 * @date 2021-01-15
 *
 *
 */

#include <algorithm>
#include <optional>
#include <queue>

#line 2 "src/graph/directed/flow/base.hpp"

/**
 * @file base.hpp
 * @brief Flow Graph
 * @date 2021-01-15
 *
 *
 */

#include <cassert>
#include <vector>

namespace workspace {

template <class Cap, class Cost = void> class flow_graph {
 public:
  class adjacency;
  using value_type = adjacency;
  using reference = adjacency &;
  using const_reference = adjacency const &;
  using container_type = std::vector<value_type>;
  using size_type = typename container_type::size_type;

  class unweighted_edge {
   public:
    size_type src, dst;
    Cap cap;
    unweighted_edge *rev;

    unweighted_edge() = default;

    unweighted_edge(size_type src, size_type dst, const Cap &cap,
                    unweighted_edge *rev)
        : src(src), dst(dst), cap(cap), rev(rev) {
      assert(!(cap < static_cast<Cap>(0)));
    }

    const Cap &flow(const Cap &f = 0) { return cap -= f, rev->cap += f; }

    unweighted_edge make_rev() { return {dst, src, 0, this}; }
  };

  class weighted_edge : public unweighted_edge {
   public:
    Cost cost;

    weighted_edge() = default;

    weighted_edge(size_type src, size_type dst, const Cap &cap,
                  const Cost &cost, weighted_edge *rev)
        : unweighted_edge(src, dst, cap, rev), cost(cost) {}

    weighted_edge make_rev() {
      return {unweighted_edge::dst, unweighted_edge::src, 0, -cost, this};
    }
  };

  using edge = typename std::conditional<std::is_void<Cost>::value,
                                         unweighted_edge, weighted_edge>::type;

  class adjacency {
   public:
    using value_type = edge;
    using reference = edge &;
    using const_reference = edge const &;
    using pointer = edge *;
    using const_pointer = const edge *;

    adjacency() : first(new edge[1]), iter(first), last(first + 1) {}
    ~adjacency() { delete[] first; }

    template <class... Args> reference emplace(Args &&... args) {
      if (iter == last) {
        size_type len(last - first);
        edge *nfst = iter = new edge[len << 1];
        for (edge *p{first}; p != last; ++p, ++iter)
          p->rev->rev = iter, *iter = *p;
        delete[] first;
        first = nfst;
        last = iter + len;
      }
      return *iter++ = edge(args...);
    }

    reference operator[](size_type i) {
      assert(i < size());
      return *(first + i);
    }
    const_reference operator[](size_type i) const {
      assert(i < size());
      return *(first + i);
    }

    size_type size() const { return iter - first; }

    pointer begin() { return first; }
    const_pointer begin() const { return first; }

    pointer end() { return iter; }
    const_pointer end() const { return iter; }

   protected:
    pointer first, iter, last;
  };

  /**
   * @brief Construct a new flow base object
   *
   * @param n Number of vertices
   */
  flow_graph(size_type n = 0) : graph(n) {}

  flow_graph(const flow_graph &other) : graph(other.size()) {
    for (size_type node = 0; node != size(); ++node)
      for (edge cp : other[node])
        if (cp.src == node) {
          edge rcp = *cp.rev;
          cp.rev->src = nil;
          edge &ref = graph[node].emplace(cp);
          rcp.rev = &ref;
          ref.rev = &graph[cp.dst].emplace(rcp);
        } else
          cp.rev->rev->src = node;
  }

  flow_graph &operator=(const flow_graph &rhs) {
    if (this != &rhs) graph.swap(flow_graph(rhs).graph);
    return *this;
  }

  /**
   * @return Number of vertices.
   */
  size_type size() const { return graph.size(); }

  reference operator[](size_type node) {
    assert(node < size());
    return graph[node];
  }

  const_reference &operator[](size_type node) const {
    assert(node < size());
    return graph[node];
  }

  typename container_type::iterator begin() { return graph.begin(); }

  typename container_type::iterator end() { return graph.end(); }

  typename container_type::const_iterator begin() const {
    return graph.begin();
  }

  typename container_type::const_iterator end() const { return graph.end(); }

  template <class... Args>
  typename adjacency::reference add_edge(size_type src, size_type dst,
                                         Args &&... args) {
    assert(src < size());
    assert(dst < size());
    auto &ref = graph[src].emplace(src, dst, args..., nullptr);
    ref.rev = &graph[dst].emplace(ref.make_rev());
    return ref;
  }

 protected:
  constexpr static size_type nil = -1;
  container_type graph;
};

}  // namespace workspace
#line 16 "src/graph/directed/flow/min_cost_flow.hpp"

namespace workspace {

/**
 * @brief Successive Shortest Path Algorithm.
 *
 * @tparam Cap Capacity type
 * @tparam Cost Cost type
 * @tparam Density_tag Whether the graph is dense.
 */
template <class Cap, class Cost, bool Density_tag = false>
class min_cost_flow : public flow_graph<Cap, Cost> {
  using base = flow_graph<Cap, Cost>;
  using base::nil;

 public:
  using edge = typename base::edge;
  using size_type = typename base::size_type;

 protected:
  Cost current, abs_sum;
  std::vector<Cap> b;
  std::vector<Cost> p;

  void copy(const min_cost_flow &other) {
    current = other.current;
    abs_sum = other.abs_sum;
    b = other.b;
    p = other.p;
  }

  void Dijkstra(std::vector<edge *> &last) {
    const Cost infty(abs_sum + 1);
    std::vector<Cost> newp(size(), infty);
    if constexpr (Density_tag) {  // O(V^2)
      std::vector<bool> used(size());
      for (size_type src{}; src != size(); ++src) {
        if (static_cast<Cap>(0) < b[src]) {
          used[src] = true;
          newp[src] = 0;
          for (edge &e : base::graph[src]) {
            if (static_cast<Cap>(0) < b[e.dst]) continue;
            if (static_cast<Cap>(0) < e.cap && e.cost < newp[e.dst]) {
              newp[e.dst] = e.cost;
              last[e.dst] = &e;
            }
          }
        }
      }
      for (;;) {
        size_type src{nil};
        Cost sp{infty};
        for (size_type node{}; node != size(); ++node) {
          if (used[node] || newp[node] == infty) continue;
          Cost dist{newp[node] - p[node]};
          if (dist < sp) {
            sp = dist;
            src = node;
          }
        }
        if (src == nil) break;
        used[src] = true;
        for (edge &e : base::graph[src]) {
          if (static_cast<Cap>(0) < e.cap && newp[src] + e.cost < newp[e.dst]) {
            newp[e.dst] = newp[src] + e.cost;
            last[e.dst] = &e;
          }
        }
      }
    } else {  // O((V + E)logV)
      struct sp_node {
        size_type id;
        Cost dist;
        sp_node(size_type id, Cost dist) : id(id), dist(dist) {}
        bool operator<(const sp_node &rhs) const { return rhs.dist < dist; }
      };
      std::priority_queue<sp_node> q;
      for (size_type src{}; src != size(); ++src)
        if (static_cast<Cap>(0) < b[src]) {
          newp[src] = 0;
          for (edge &e : base::graph[src])
            if (!(static_cast<Cap>(0) < b[e.dst]) &&
                static_cast<Cap>(0) < e.cap && newp[e.dst] > e.cost) {
              q.emplace(e.dst, (newp[e.dst] = e.cost) - p[e.dst]);
              last[e.dst] = &e;
            }
        }
      while (!q.empty()) {
        auto [src, ndist] = q.top();
        q.pop();
        if (ndist + p[src] != newp[src]) continue;
        for (edge &e : base::graph[src])
          if (static_cast<Cap>(0) < e.cap && newp[e.dst] > newp[src] + e.cost) {
            q.emplace(e.dst, (newp[e.dst] = newp[src] + e.cost) - p[e.dst]);
            last[e.dst] = &e;
          }
      }
    }
    p.swap(newp);
  }

 public:
  using base::size;

  /**
   * @brief Construct a new object
   *
   * @param n Number of vertices.
   */
  min_cost_flow(size_type n = 0)
      : base::flow_graph(n), current(0), abs_sum(0), b(n), p(n) {}

  min_cost_flow(const min_cost_flow &other) : base::flow_graph(other) {
    copy(other);
  }

  min_cost_flow &operator=(const min_cost_flow &other) {
    base::operator=(other);
    copy(other);
    return *this;
  }

  // infinity capatity
  // edge *add_edge(size_type src, size_type dst, const Cost &cost);

  /**
   * @brief Add an edge to the graph.
   *
   * @param src Source
   * @param dst Destination
   * @param cap Capacity
   * @param cost Cost
   * @return Reference to the edge.
   */
  typename base::adjacency::reference add_edge(size_type src, size_type dst,
                                               const Cap &cap,
                                               const Cost &cost) {
    assert(src != dst);
    if (cost < static_cast<Cost>(0)) {
      b[src] -= cap;
      b[dst] += cap;
      current += cap * cost;
      abs_sum -= cap * cost;
      return base::add_edge(dst, src, cap, -cost);
    }
    abs_sum += cap * cost;
    return base::add_edge(src, dst, cap, cost);
  }

  /**
   * @brief Add an edge to the graph.
   *
   * @param src Source
   * @param dst Destination
   * @param lower Lower bound of flow
   * @param upper Upper bound of flow
   * @param cost Cost
   * @return Reference to the edge.
   */
  typename base::adjacency::reference add_edge(size_type src, size_type dst,
                                               const Cap &lower,
                                               const Cap &upper,
                                               const Cost &cost) {
    assert(!(upper < lower));
    b[src] -= lower;
    b[dst] += lower;
    current += lower * cost;
    return add_edge(src, dst, upper - lower, cost);
  }

  /**
   * @brief Increase the balance of a node.
   *
   * @param node
   * @param vol
   */
  void supply(size_type node, const Cap &vol) {
    assert(node < size());
    b[node] += vol;
  }

  /**
   * @brief Decrease the balance of a node.
   *
   * @param node
   * @param vol
   */
  void demand(size_type node, const Cap &vol) { supply(node, -vol); }

  /**
   * @param node
   * @return Balance of the node
   */
  Cap balance(size_type node) { return b[node]; }

  /**
   * @return Cost of current flow.
   */
  Cost cost() const { return current; }

  /**
   * @brief Run Successive Shortest Path Algorithm.
   *
   * @return Whether a balanced flow exists.
   */
  bool flow() {
    for (bool aug = true; aug;) {
      aug = false;
      std::vector<edge *> last(size());
      Dijkstra(last);
      std::vector<bool> shut(size());
      for (size_type dst{}; dst != size(); ++dst) {
        if (b[dst] < static_cast<Cap>(0) and last[dst]) {
          Cap resid{-b[dst]};
          size_type src{dst}, block{nil};
          while (last[src] && !shut[src]) {
            if (!(resid < last[src]->cap)) resid = last[block = src]->cap;
            src = last[src]->src;
          }
          if (shut[src])
            block = src;
          else {
            if (!(resid < b[src])) resid = b[block = src];
            for (edge *e{last[dst]}; e; e = last[e->src]) {
              e->cap -= resid;
              e->rev->cap += resid;
            }
            b[src] -= resid;
            b[dst] += resid;
            current += p[dst] * resid;
            aug = true;
          }
          if (~block) {
            for (size_type node{dst};; node = last[node]->src) {
              shut[node] = true;
              if (node == block) break;
            }
          }
        }
      }
    }
    return std::none_of(begin(b), end(b), [](const Cap &s) {
      return s < static_cast<Cap>(0) || static_cast<Cap>(0) < s;
    });
  }
};

}  // namespace workspace
#line 6 "test/aizu-online-judge/2815.test.cpp"

int main() {
  using namespace workspace;

  int n, m, k;
  std::cin >> n >> m >> k;
  const int total = n + m + 3;
  const int dst = total - 1;
  const int dst2 = total - 2;
  const int dst3 = total - 3;
  min_cost_flow<int, int, true> mcf(total);
  mcf.supply(dst, -n);
  mcf.add_edge(dst2, dst, n, 0);
  mcf.add_edge(dst3, dst, n - k, 0);
  for (int i = 0; i < n; ++i) {
    mcf.supply(i, 1);
    std::cin >> k;
    mcf.add_edge(i, dst2, 1, -k);
  }
  for (int j = 0; j < m; j++) {
    for (int i = 0; i < n; i++) {
      std::cin >> k;
      mcf.add_edge(i, j + n, 1, -k);
    }
  }
  for (int j = 0; j < m; j++) {
    std::cin >> k;
    mcf.add_edge(j + n, dst3, k, 0);
  }
  assert(mcf.flow());
  std::cout << -mcf.cost() << "\n";
}
accuracy: 1
time_ms: 10
memory_kb: 4320
final_rank: 8

code_snippet: #include <bits/stdc++.h>

namespace std
{
    // hash
    template <class T> size_t hash_combine(size_t seed, T const &key) { return seed ^ (hash<T>()(key) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); }
    template <class T, class U> struct hash<pair<T, U>> { size_t operator()(pair<T, U> const &pr) const { return hash_combine(hash_combine(0, pr.first), pr.second); } };
    template <class tuple_t, size_t index = tuple_size<tuple_t>::value - 1> struct tuple_hash_calc { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(tuple_hash_calc<tuple_t, index - 1>::apply(seed, t), get<index>(t)); } };
    template <class tuple_t> struct tuple_hash_calc<tuple_t, 0> { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(seed, get<0>(t)); } };
    template <class... T> struct hash<tuple<T...>> { size_t operator()(tuple<T...> const &t) const { return tuple_hash_calc<tuple<T...>>::apply(0, t); } };
    // iostream
    template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) { return is >> p.first >> p.second; }
    template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { return os << p.first << ' ' << p.second; }
    template <class tuple_t, size_t index> struct tupleos { static ostream &apply(ostream &os, const tuple_t &t) { tupleos<tuple_t, index - 1>::apply(os, t); return os << ' ' << get<index>(t); } };
    template <class tuple_t> struct tupleos<tuple_t, 0> { static ostream &apply(ostream &os, const tuple_t &t) { return os << get<0>(t); } };
    template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t)  { return tupleos<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os, t); }
    template <> ostream &operator<<(ostream &os, const tuple<> &t) { return os; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    istream& operator>>(istream& is, Container &cont) { for(auto&& e : cont) is >> e; return is; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    ostream& operator<<(ostream& os, const Container &cont) { bool flag = 1; for(auto&& e : cont) flag ? flag = 0 : (os << ' ', 0), os << e; return os; }
} // namespace std


template <class cap_t, class cost_t>
struct Flow
{
    Flow(size_t _V) : V(_V), adj(_V) {}
    void add_edge(size_t from, size_t to, cap_t cap, cost_t cost = cost_t(0))
    {
        if(cap <= 0) return;
        adj[from].emplace_back(from, to, cap, cost, adj[to].size());
        adj[to].emplace_back(to, from, 0, -cost, adj[from].size() - 1);
    }
  protected:
    struct edge
    {
        size_t from, to; cap_t cap; cost_t cost; size_t rev;
        edge(size_t _from, size_t _to, cap_t _cap, cost_t _cost, size_t _rev) : from(_from), to(_to), cap(_cap), cost(_cost), rev(_rev) {}
    }; // struct edge
    size_t V;
    std::vector<std::vector<edge>> adj;
}; // struct Flow

template <class cap_t, class cost_t>
class Primal_Dual : public Flow<cap_t, cost_t>
{
    using edge = typename Flow<cap_t, cap_t>::edge;
    using Flow<cap_t, cap_t>::V; using Flow<cap_t, cap_t>::adj;
    bool neg_cost;
/*    std::vector<cost_t> dist, h;
    std::vector<size_t> prev_v;
    std::vector<edge*> prev_e;
    bool dijkstra(size_t s, size_t t)
    {
        // using info = std::pair<cost_t, size_t>;
        // std::priority_queue<info, std::vector<info>, std::greater<info>> que;
        // fill(dist.begin(), dist.end(), inf_cost);
        // que.emplace(dist[s] = 0, s);
        // while(!que.empty())
        // {
        //     cost_t _cost; size_t v;
        //     std::tie(_cost, v) = que.top(), que.pop();
        //     if(_cost != dist[v]) continue;
        //     for(auto &&e : adj[v])
        //     {
        //         if(e.cap > 0 && dist[v] + h[v] + e.cost < dist[e.to] + h[e.to])
        //         {
        //             que.emplace(dist[e.to] = dist[v] + h[v] - h[e.to] + e.cost, e.to);
        //             prev_v[e.to] = v;
        //             prev_e[e.to] = &e;
        //         }
        //     }
        // }

        bool *used = new bool[V]{};
        for(fill(dist.begin(), dist.end(), inf_cost), dist[s] = 0; ; )
        {
            size_t nowv = -1;
            cost_t opt = inf_cost;
            for(size_t v = 0; v != V; ++v)
            {
                if(!used[v] && opt > dist[v] + h[v])
                {
                    opt = dist[v] + h[v];
                    nowv = v;
                }
            }
            if(nowv == -1) break;
            used[nowv] = true;
            for(auto &&e : adj[nowv])
            {
                if(e.cap > 0 && dist[e.to] + h[e.to] > opt + e.cost)
                {
                    dist[e.to] = opt - h[e.to] + e.cost;
                    prev_v[e.to] = nowv;
                    prev_e[e.to] = &e;
                }
            }
        }
        delete[] used;

        if(dist[t] >= inf_cost) return false;
        for(size_t v = 0; v != V; ++v)
        {
            h[v] += dist[v];
            if(h[v] > inf_cost) h[v] = inf_cost;
        }
        return true;
    } */
  public:
    const cost_t inf_cost = std::numeric_limits<cost_t>::max() / 4;
    Primal_Dual(size_t V) : Flow<cap_t, cost_t>(V), neg_cost() {}
    void add_edge(size_t s, size_t t, cap_t cap, cost_t cost)
    {
        if(cap <= 0) return;
        if(cost < 0) neg_cost = true;
        Flow<cap_t, cost_t>::add_edge(s, t, cap, cost);
    }
    cost_t min_cost_flow(size_t s, size_t t, cap_t f)
    {
        cost_t res = 0;
        if(neg_cost)
        {
            neg_cost = false;
            {
                const size_t _s = V++, _t = V++;
                adj.resize(V);
                add_edge(_s, s, f, 0);
                add_edge(t, _t, f, 0);
                s = _s, t = _t;
            }
            std::vector<cap_t> scap(V), tcap(V);
            for(size_t v = 0; v != V; ++v)
            {
                cap_t cap_sum = 0;
                for(auto &&e : adj[v])
                {
                    if(e.cap > 0 and e.cost < 0)
                    {
                        scap[e.to] += e.cap;
                        tcap[v] += e.cap;
                        res += e.cap * e.cost;
                        f += e.cap;
                        adj[e.to][e.rev].cap += e.cap;
                        cap_sum += e.cap;
                        e.cap = 0;
                    }
                }
            }
            for(size_t v = 0; v != V; ++v)
            {
                add_edge(s, v, scap[v], 0);
                add_edge(v, t, tcap[v], 0);
            }
        }
        std::vector<cost_t> h(V);
        std::vector<size_t> prev_v(V);
        std::vector<edge*> prev_e(V);
        bool *const used = new bool[V];
        while(f > 0)
        {
            std::fill_n(used, V, false);
            std::vector<cost_t> dist(V, inf_cost);
        using info = std::pair<cost_t, size_t>;
        std::priority_queue<info, std::vector<info>, std::greater<info>> que;
        que.emplace(dist[s] = 0, s);
        while(!que.empty())
        {
            cost_t _cost; size_t v;
            std::tie(_cost, v) = que.top(), que.pop();
            if(_cost != dist[v]) continue;
            for(auto &&e : adj[v])
            {
                if(e.cap > 0 && dist[v] + h[v] + e.cost < dist[e.to] + h[e.to])
                {
                    que.emplace(dist[e.to] = dist[v] + h[v] - h[e.to] + e.cost, e.to);
                    prev_v[e.to] = v;
                    prev_e[e.to] = &e;
                }
            }
        }
            if(dist[t] >= inf_cost)
            {
                res = inf_cost;
                break;
            }
            for(size_t v = 0; v != V; ++v)
            {
                h[v] += dist[v];
                if(h[v] > inf_cost) h[v] = inf_cost;
            }
            cap_t d = f;
            for(size_t v = t; v != s; v = prev_v[v]) d = std::min(d, prev_e[v]->cap);
            f -= d, res += h[t] * d;
            for(size_t v = t; v != s; v = prev_v[v])
            {
                prev_e[v]->cap -= d;
                adj[v][prev_e[v]->rev].cap += d;
            }
        }
        delete[] used;
        return res;
    }
}; // class Primal_Dual

main()
{
    using namespace std;
    int n,m,k; cin>>n>>m>>k;
    Primal_Dual<int,int> flow(2+n+m);
    vector<int> a(n); cin>>a;
    const int s=n+m,t=s+1;
    for(int i=0; i<m; ++i)
    {
        for(int j=0; j<n; ++j)
        {
            int b; cin>>b;
            flow.add_edge(i,j+m,1,-b);
        }
    }
    for(int i=m; i<m+n; ++i)
    {
        flow.add_edge(i,t,1,a[i-m]);
    }
    for(int i=0; i<m; ++i)
    {
        int t; cin>>t;
        flow.add_edge(s,i,t,0);
    }
    flow.add_edge(s,t,n,0);
    cout << accumulate(a.begin(),a.end(),0)-flow.min_cost_flow(s,t,n-k) << "\n";

}
accuracy: 1
time_ms: 700
memory_kb: 3700
final_rank: 10

code_snippet: #include <bits/stdc++.h>

namespace std
{
    // hash
    template <class T> size_t hash_combine(size_t seed, T const &key) { return seed ^ (hash<T>()(key) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); }
    template <class T, class U> struct hash<pair<T, U>> { size_t operator()(pair<T, U> const &pr) const { return hash_combine(hash_combine(0, pr.first), pr.second); } };
    template <class tuple_t, size_t index = tuple_size<tuple_t>::value - 1> struct tuple_hash_calc { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(tuple_hash_calc<tuple_t, index - 1>::apply(seed, t), get<index>(t)); } };
    template <class tuple_t> struct tuple_hash_calc<tuple_t, 0> { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(seed, get<0>(t)); } };
    template <class... T> struct hash<tuple<T...>> { size_t operator()(tuple<T...> const &t) const { return tuple_hash_calc<tuple<T...>>::apply(0, t); } };
    // iostream
    template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) { return is >> p.first >> p.second; }
    template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { return os << p.first << ' ' << p.second; }
    template <class tuple_t, size_t index> struct tupleos { static ostream &apply(ostream &os, const tuple_t &t) { tupleos<tuple_t, index - 1>::apply(os, t); return os << ' ' << get<index>(t); } };
    template <class tuple_t> struct tupleos<tuple_t, 0> { static ostream &apply(ostream &os, const tuple_t &t) { return os << get<0>(t); } };
    template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t)  { return tupleos<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os, t); }
    template <> ostream &operator<<(ostream &os, const tuple<> &t) { return os; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    istream& operator>>(istream& is, Container &cont) { for(auto&& e : cont) is >> e; return is; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    ostream& operator<<(ostream& os, const Container &cont) { bool flag = 1; for(auto&& e : cont) flag ? flag = 0 : (os << ' ', 0), os << e; return os; }
} // namespace std


template <class cap_t, class cost_t>
struct Flow
{
    Flow(size_t _V) : V(_V), adj(_V) {}
    void add_edge(size_t from, size_t to, cap_t cap, cost_t cost = cost_t(0))
    {
        if(cap <= 0) return;
        adj[from].emplace_back(from, to, cap, cost, adj[to].size());
        adj[to].emplace_back(to, from, 0, -cost, adj[from].size() - 1);
    }
  protected:
    struct edge
    {
        size_t from, to; cap_t cap; cost_t cost; size_t rev;
        edge(size_t _from, size_t _to, cap_t _cap, cost_t _cost, size_t _rev) : from(_from), to(_to), cap(_cap), cost(_cost), rev(_rev) {}
    }; // struct edge
    size_t V;
    std::vector<std::vector<edge>> adj;
}; // struct Flow

template <class cap_t, class cost_t>
class Primal_Dual : public Flow<cap_t, cost_t>
{
    using edge = typename Flow<cap_t, cap_t>::edge;
    using Flow<cap_t, cap_t>::V; using Flow<cap_t, cap_t>::adj;
    bool neg_cost;
/*    std::vector<cost_t> dist, h;
    std::vector<size_t> prev_v;
    std::vector<edge*> prev_e;
    bool dijkstra(size_t s, size_t t)
    {
        // using info = std::pair<cost_t, size_t>;
        // std::priority_queue<info, std::vector<info>, std::greater<info>> que;
        // fill(dist.begin(), dist.end(), inf_cost);
        // que.emplace(dist[s] = 0, s);
        // while(!que.empty())
        // {
        //     cost_t _cost; size_t v;
        //     std::tie(_cost, v) = que.top(), que.pop();
        //     if(_cost != dist[v]) continue;
        //     for(auto &&e : adj[v])
        //     {
        //         if(e.cap > 0 && dist[v] + h[v] + e.cost < dist[e.to] + h[e.to])
        //         {
        //             que.emplace(dist[e.to] = dist[v] + h[v] - h[e.to] + e.cost, e.to);
        //             prev_v[e.to] = v;
        //             prev_e[e.to] = &e;
        //         }
        //     }
        // }

        bool *used = new bool[V]{};
        for(fill(dist.begin(), dist.end(), inf_cost), dist[s] = 0; ; )
        {
            size_t nowv = -1;
            cost_t opt = inf_cost;
            for(size_t v = 0; v != V; ++v)
            {
                if(!used[v] && opt > dist[v] + h[v])
                {
                    opt = dist[v] + h[v];
                    nowv = v;
                }
            }
            if(nowv == -1) break;
            used[nowv] = true;
            for(auto &&e : adj[nowv])
            {
                if(e.cap > 0 && dist[e.to] + h[e.to] > opt + e.cost)
                {
                    dist[e.to] = opt - h[e.to] + e.cost;
                    prev_v[e.to] = nowv;
                    prev_e[e.to] = &e;
                }
            }
        }
        delete[] used;

        if(dist[t] >= inf_cost) return false;
        for(size_t v = 0; v != V; ++v)
        {
            h[v] += dist[v];
            if(h[v] > inf_cost) h[v] = inf_cost;
        }
        return true;
    } */
  public:
    const cost_t inf_cost = std::numeric_limits<cost_t>::max() / 4;
    Primal_Dual(size_t V) : Flow<cap_t, cost_t>(V), neg_cost() {}
    void add_edge(size_t s, size_t t, cap_t cap, cost_t cost)
    {
        if(cap <= 0) return;
        if(cost < 0) neg_cost = true;
        Flow<cap_t, cost_t>::add_edge(s, t, cap, cost);
    }
    cost_t min_cost_flow(size_t s, size_t t, cap_t f)
    {
        cost_t res = 0;
        if(neg_cost)
        {
            neg_cost = false;
            {
                const size_t _s = V++, _t = V++;
                adj.resize(V);
                add_edge(_s, s, f, 0);
                add_edge(t, _t, f, 0);
                s = _s, t = _t;
            }
            std::vector<cap_t> scap(V), tcap(V);
            for(size_t v = 0; v != V; ++v)
            {
                cap_t cap_sum = 0;
                for(auto &&e : adj[v])
                {
                    if(e.cap > 0 and e.cost < 0)
                    {
                        scap[e.to] += e.cap;
                        tcap[v] += e.cap;
                        res += e.cap * e.cost;
                        f += e.cap;
                        adj[e.to][e.rev].cap += e.cap;
                        cap_sum += e.cap;
                        e.cap = 0;
                    }
                }
            }
            for(size_t v = 0; v != V; ++v)
            {
                add_edge(s, v, scap[v], 0);
                add_edge(v, t, tcap[v], 0);
            }
        }
        std::vector<cost_t> h(V);
        std::vector<size_t> prev_v(V);
        std::vector<edge*> prev_e(V);
        bool *const used = new bool[V];
        while(f > 0)
        {
            std::fill_n(used, V, false);
            std::vector<cost_t> dist(V, inf_cost);
            dist[s] = 0;
            while(true)
            {
                size_t v = -1;
                cost_t opt = inf_cost;
                for(size_t u = 0; u != V; ++u)
                {
                    if(!used[u] && opt > dist[u])
                    {
                        opt = dist[u];
                        v = u;
                    }
                }
                if(v == -1) break;
                opt += h[v];
                used[v] = true;
                for(auto &&e : adj[v])
                {
                    if(e.cap > 0 && dist[e.to] + h[e.to] > opt + e.cost)
                    {
                        dist[e.to] = opt - h[e.to] + e.cost;
                        prev_v[e.to] = v;
                        prev_e[e.to] = &e;
                    }
                }
            }
            if(dist[t] >= inf_cost)
            {
                res = inf_cost;
                break;
            }
            for(size_t v = 0; v != V; ++v)
            {
                h[v] += dist[v];
                if(h[v] > inf_cost) h[v] = inf_cost;
            }
            cap_t d = f;
            for(size_t v = t; v != s; v = prev_v[v]) d = std::min(d, prev_e[v]->cap);
            f -= d, res += h[t] * d;
            for(size_t v = t; v != s; v = prev_v[v])
            {
                prev_e[v]->cap -= d;
                adj[v][prev_e[v]->rev].cap += d;
            }
        }
        delete[] used;
        return res;
    }
}; // class Primal_Dual

main()
{
    using namespace std;
    int n,m,k; cin>>n>>m>>k;
    Primal_Dual<int,int> flow(2+n+m);
    vector<int> a(n); cin>>a;
    const int s=n+m,t=s+1;
    for(int i=0; i<m; ++i)
    {
        for(int j=0; j<n; ++j)
        {
            int b; cin>>b;
            flow.add_edge(i,j+m,1,-b);
        }
    }
    for(int i=m; i<m+n; ++i)
    {
        flow.add_edge(i,t,1,a[i-m]);
    }
    for(int i=0; i<m; ++i)
    {
        int t; cin>>t;
        flow.add_edge(s,i,t,0);
    }
    flow.add_edge(s,t,n,0);
    cout << accumulate(a.begin(),a.end(),0)-flow.min_cost_flow(s,t,n-k) << "\n";

}
accuracy: 1
time_ms: 1050
memory_kb: 3600
final_rank: 13

code_snippet: #include <bits/stdc++.h>

namespace std
{
    // hash
    template <class T> size_t hash_combine(size_t seed, T const &key) { return seed ^ (hash<T>()(key) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); }
    template <class T, class U> struct hash<pair<T, U>> { size_t operator()(pair<T, U> const &pr) const { return hash_combine(hash_combine(0, pr.first), pr.second); } };
    template <class tuple_t, size_t index = tuple_size<tuple_t>::value - 1> struct tuple_hash_calc { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(tuple_hash_calc<tuple_t, index - 1>::apply(seed, t), get<index>(t)); } };
    template <class tuple_t> struct tuple_hash_calc<tuple_t, 0> { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(seed, get<0>(t)); } };
    template <class... T> struct hash<tuple<T...>> { size_t operator()(tuple<T...> const &t) const { return tuple_hash_calc<tuple<T...>>::apply(0, t); } };
    // iostream
    template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) { return is >> p.first >> p.second; }
    template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { return os << p.first << ' ' << p.second; }
    template <class tuple_t, size_t index> struct tupleos { static ostream &apply(ostream &os, const tuple_t &t) { tupleos<tuple_t, index - 1>::apply(os, t); return os << ' ' << get<index>(t); } };
    template <class tuple_t> struct tupleos<tuple_t, 0> { static ostream &apply(ostream &os, const tuple_t &t) { return os << get<0>(t); } };
    template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t)  { return tupleos<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os, t); }
    template <> ostream &operator<<(ostream &os, const tuple<> &t) { return os; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    istream& operator>>(istream& is, Container &cont) { for(auto&& e : cont) is >> e; return is; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    ostream& operator<<(ostream& os, const Container &cont) { bool flag = 1; for(auto&& e : cont) flag ? flag = 0 : (os << ' ', 0), os << e; return os; }
} // namespace std


template <class cap_t, class cost_t>
struct Flow
{
    Flow(size_t _V) : V(_V), adj(_V) {}
    void add_edge(size_t from, size_t to, cap_t cap, cost_t cost = cost_t(0))
    {
        if(cap <= 0) return;
        adj[from].emplace_back(from, to, cap, cost, adj[to].size());
        adj[to].emplace_back(to, from, 0, -cost, adj[from].size() - 1);
    }
  protected:
    struct edge
    {
        size_t from, to; cap_t cap; cost_t cost; size_t rev;
        edge(size_t _from, size_t _to, cap_t _cap, cost_t _cost, size_t _rev) : from(_from), to(_to), cap(_cap), cost(_cost), rev(_rev) {}
    }; // struct edge
    size_t V;
    std::vector<std::vector<edge>> adj;
}; // struct Flow

template <class cap_t, class cost_t>
class Primal_Dual : public Flow<cap_t, cost_t>
{
    using edge = typename Flow<cap_t, cap_t>::edge;
    using Flow<cap_t, cap_t>::V; using Flow<cap_t, cap_t>::adj;
    bool neg_cost;
    std::vector<cost_t> dist, h;
    std::vector<size_t> prev_v;
    std::vector<edge*> prev_e;
    bool *used;
    bool dijkstra(size_t s, size_t t)
    {
/*        using info = std::pair<cost_t, size_t>;
        std::priority_queue<info, std::vector<info>, std::greater<info>> que;
        fill(dist.begin(), dist.end(), inf_cost);
        que.emplace(dist[s] = 0, s);
        while(!que.empty())
        {
            cost_t _cost; size_t v;
            std::tie(_cost, v) = que.top(), que.pop();
            if(_cost != dist[v]) continue;
            for(auto &&e : adj[v])
            {
                if(e.cap > 0 && dist[v] + h[v] + e.cost < dist[e.to] + h[e.to])
                {
                    que.emplace(dist[e.to] = dist[v] + h[v] - h[e.to] + e.cost, e.to);
                    prev_v[e.to] = v;
                    prev_e[e.to] = &e;
                }
            }
        }
*/
        // bool *used = new bool[V]{};
        for(std::fill_n(used, V, false), fill(dist.begin(), dist.end(), inf_cost), dist[s] = 0; ; )
        {
            size_t nowv = -1;
            cost_t opt = inf_cost;
            for(size_t v = 0; v != V; ++v)
            {
                if(!used[v] && opt > dist[v])
                {
                    opt = dist[v];
                    nowv = v;
                }
            }
            if(nowv == -1) break;
            opt += h[nowv];
            used[nowv] = true;
            for(auto &&e : adj[nowv])
            {
                if(e.cap > 0 && dist[e.to] + h[e.to] > opt + e.cost)
                {
                    dist[e.to] = opt - h[e.to] + e.cost;
                    prev_v[e.to] = nowv;
                    prev_e[e.to] = &e;
                }
            }
        }
        // delete[] used;

        if(dist[t] >= inf_cost) return false;
        for(size_t v = 0; v != V; ++v)
        {
            h[v] += dist[v];
            if(h[v] > inf_cost) h[v] = inf_cost;
        }
        return true;
    }
  public:
    const cost_t inf_cost = std::numeric_limits<cost_t>::max() / 4;
    Primal_Dual(size_t V) : Flow<cap_t, cost_t>(V), neg_cost() {}
    ~Primal_Dual() { delete[] used; }
    void add_edge(size_t s, size_t t, cap_t cap, cost_t cost)
    {
        if(cap <= 0) return;
        if(cost < 0) neg_cost = true;
        Flow<cap_t, cost_t>::add_edge(s, t, cap, cost);
    }
    cost_t min_cost_flow(size_t s, size_t t, cap_t f)
    {
        cost_t res = 0;
        if(neg_cost)
        {
            neg_cost = false;
            {
                const size_t _s = V++, _t = V++;
                adj.resize(V);
                add_edge(_s, s, f, 0);
                add_edge(t, _t, f, 0);
                s = _s, t = _t;
            }
            std::vector<cap_t> scap(V), tcap(V);
            for(size_t v = 0; v != V; ++v)
            {
                cap_t cap_sum = 0;
                for(auto &&e : adj[v])
                {
                    if(e.cap > 0 and e.cost < 0)
                    {
                        scap[e.to] += e.cap;
                        tcap[v] += e.cap;
                        res += e.cap * e.cost;
                        f += e.cap;
                        adj[e.to][e.rev].cap += e.cap;
                        cap_sum += e.cap;
                        e.cap = 0;
                    }
                }
            }
            for(size_t v = 0; v != V; ++v)
            {
                add_edge(s, v, scap[v], 0);
                add_edge(v, t, tcap[v], 0);
            }
        }
        // delete[] used; 
        used = new bool[V];
        dist.resize(V), h.assign(V, 0);
        prev_v.resize(V), prev_e.resize(V);
        while(f > 0)
        {
            if(!dijkstra(s, t)) return inf_cost;
            cap_t d = f;
            for(size_t v = t; v != s; v = prev_v[v]) d = std::min(d, prev_e[v]->cap);
            f -= d, res += h[t] * d;
            for(size_t v = t; v != s; v = prev_v[v])
            {
                prev_e[v]->cap -= d;
                adj[v][prev_e[v]->rev].cap += d;
            }
        }
        return res;
    }
}; // class Primal_Dual

main()
{
    using namespace std;
    int n,m,k; cin>>n>>m>>k;
    Primal_Dual<int,int> flow(2+n+m);
    vector<int> a(n); cin>>a;
    const int s=n+m,t=s+1;
    for(int i=0; i<m; ++i)
    {
        for(int j=0; j<n; ++j)
        {
            int b; cin>>b;
            flow.add_edge(i,j+m,1,-b);
        }
    }
    for(int i=m; i<m+n; ++i)
    {
        flow.add_edge(i,t,1,a[i-m]);
    }
    for(int i=0; i<m; ++i)
    {
        int t; cin>>t;
        flow.add_edge(s,i,t,0);
    }
    flow.add_edge(s,t,n,0);
    cout << accumulate(a.begin(),a.end(),0)-flow.min_cost_flow(s,t,n-k) << "\n";

}
accuracy: 1
time_ms: 1040
memory_kb: 3644
final_rank: 15

code_snippet: #include <bits/stdc++.h>

namespace std
{
    // hash
    template <class T> size_t hash_combine(size_t seed, T const &key) { return seed ^ (hash<T>()(key) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); }
    template <class T, class U> struct hash<pair<T, U>> { size_t operator()(pair<T, U> const &pr) const { return hash_combine(hash_combine(0, pr.first), pr.second); } };
    template <class tuple_t, size_t index = tuple_size<tuple_t>::value - 1> struct tuple_hash_calc { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(tuple_hash_calc<tuple_t, index - 1>::apply(seed, t), get<index>(t)); } };
    template <class tuple_t> struct tuple_hash_calc<tuple_t, 0> { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(seed, get<0>(t)); } };
    template <class... T> struct hash<tuple<T...>> { size_t operator()(tuple<T...> const &t) const { return tuple_hash_calc<tuple<T...>>::apply(0, t); } };
    // iostream
    template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) { return is >> p.first >> p.second; }
    template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { return os << p.first << ' ' << p.second; }
    template <class tuple_t, size_t index> struct tupleos { static ostream &apply(ostream &os, const tuple_t &t) { tupleos<tuple_t, index - 1>::apply(os, t); return os << ' ' << get<index>(t); } };
    template <class tuple_t> struct tupleos<tuple_t, 0> { static ostream &apply(ostream &os, const tuple_t &t) { return os << get<0>(t); } };
    template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t)  { return tupleos<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os, t); }
    template <> ostream &operator<<(ostream &os, const tuple<> &t) { return os; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    istream& operator>>(istream& is, Container &cont) { for(auto&& e : cont) is >> e; return is; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    ostream& operator<<(ostream& os, const Container &cont) { bool flag = 1; for(auto&& e : cont) flag ? flag = 0 : (os << ' ', 0), os << e; return os; }
} // namespace std


template <class cap_t, class cost_t>
struct Flow
{
    Flow(size_t _V) : V(_V), adj(_V) {}
    void add_edge(size_t from, size_t to, cap_t cap, cost_t cost = cost_t(0))
    {
        if(cap <= 0) return;
        adj[from].emplace_back(from, to, cap, cost, adj[to].size());
        adj[to].emplace_back(to, from, 0, -cost, adj[from].size() - 1);
    }
  protected:
    struct edge
    {
        size_t from, to; cap_t cap; cost_t cost; size_t rev;
        edge(size_t _from, size_t _to, cap_t _cap, cost_t _cost, size_t _rev) : from(_from), to(_to), cap(_cap), cost(_cost), rev(_rev) {}
    }; // struct edge
    size_t V;
    std::vector<std::vector<edge>> adj;
}; // struct Flow

template <class cap_t, class cost_t>
class Primal_Dual : public Flow<cap_t, cost_t>
{
    using edge = typename Flow<cap_t, cap_t>::edge;
    using Flow<cap_t, cap_t>::V; using Flow<cap_t, cap_t>::adj;
    bool neg_cost;
    std::vector<cost_t> dist, h;
    std::vector<size_t> prev_v;
    std::vector<edge*> prev_e;
    bool *const used;
    bool dijkstra(size_t s, size_t t)
    {
/*        using info = std::pair<cost_t, size_t>;
        std::priority_queue<info, std::vector<info>, std::greater<info>> que;
        fill(dist.begin(), dist.end(), inf_cost);
        que.emplace(dist[s] = 0, s);
        while(!que.empty())
        {
            cost_t _cost; size_t v;
            std::tie(_cost, v) = que.top(), que.pop();
            if(_cost != dist[v]) continue;
            for(auto &&e : adj[v])
            {
                if(e.cap > 0 && dist[v] + h[v] + e.cost < dist[e.to] + h[e.to])
                {
                    que.emplace(dist[e.to] = dist[v] + h[v] - h[e.to] + e.cost, e.to);
                    prev_v[e.to] = v;
                    prev_e[e.to] = &e;
                }
            }
        }
*/
        // bool *used = new bool[V]{};
        for(std::fill_n(used, V, false), fill(dist.begin(), dist.end(), inf_cost), dist[s] = 0; ; )
        {
            size_t nowv = -1;
            cost_t opt = inf_cost;
            for(size_t v = 0; v != V; ++v)
            {
                if(!used[v] && opt > dist[v])
                {
                    opt = dist[v];
                    nowv = v;
                }
            }
            if(nowv == -1) break;
            opt += h[nowv];
            used[nowv] = true;
            for(auto &&e : adj[nowv])
            {
                if(e.cap > 0 && dist[e.to] + h[e.to] > opt + e.cost)
                {
                    dist[e.to] = opt - h[e.to] + e.cost;
                    prev_v[e.to] = nowv;
                    prev_e[e.to] = &e;
                }
            }
        }
        // delete[] used;

        if(dist[t] >= inf_cost) return false;
        for(size_t v = 0; v != V; ++v)
        {
            h[v] += dist[v];
            if(h[v] > inf_cost) h[v] = inf_cost;
        }
        return true;
    }
  public:
    const cost_t inf_cost = std::numeric_limits<cost_t>::max() / 4;
    Primal_Dual(size_t V) : Flow<cap_t, cost_t>(V), neg_cost(), used(new bool[V]) {}
    ~Primal_Dual() { delete[] used; }
    void add_edge(size_t s, size_t t, cap_t cap, cost_t cost)
    {
        if(cap <= 0) return;
        if(cost < 0) neg_cost = true;
        Flow<cap_t, cost_t>::add_edge(s, t, cap, cost);
    }
    cost_t min_cost_flow(size_t s, size_t t, cap_t f)
    {
        cost_t res = 0;
        if(neg_cost)
        {
            neg_cost = false;
            {
                const size_t _s = V++, _t = V++;
                adj.resize(V);
                add_edge(_s, s, f, 0);
                add_edge(t, _t, f, 0);
                s = _s, t = _t;
            }
            std::vector<cap_t> scap(V), tcap(V);
            for(size_t v = 0; v != V; ++v)
            {
                cap_t cap_sum = 0;
                for(auto &&e : adj[v])
                {
                    if(e.cap > 0 and e.cost < 0)
                    {
                        scap[e.to] += e.cap;
                        tcap[v] += e.cap;
                        res += e.cap * e.cost;
                        f += e.cap;
                        adj[e.to][e.rev].cap += e.cap;
                        cap_sum += e.cap;
                        e.cap = 0;
                    }
                }
            }
            for(size_t v = 0; v != V; ++v)
            {
                add_edge(s, v, scap[v], 0);
                add_edge(v, t, tcap[v], 0);
            }
        }
        dist.resize(V), h.assign(V, 0);
        prev_v.resize(V), prev_e.resize(V);
        while(f > 0)
        {
            if(!dijkstra(s, t)) return inf_cost;
            cap_t d = f;
            for(size_t v = t; v != s; v = prev_v[v]) d = std::min(d, prev_e[v]->cap);
            f -= d, res += h[t] * d;
            for(size_t v = t; v != s; v = prev_v[v])
            {
                prev_e[v]->cap -= d;
                adj[v][prev_e[v]->rev].cap += d;
            }
        }
        return res;
    }
}; // class Primal_Dual

main()
{
    using namespace std;
    int n,m,k; cin>>n>>m>>k;
    Primal_Dual<int,int> flow(2+n+m);
    vector<int> a(n); cin>>a;
    const int s=n+m,t=s+1;
    for(int i=0; i<m; ++i)
    {
        for(int j=0; j<n; ++j)
        {
            int b; cin>>b;
            flow.add_edge(i,j+m,1,-b);
        }
    }
    for(int i=m; i<m+n; ++i)
    {
        flow.add_edge(i,t,1,a[i-m]);
    }
    for(int i=0; i<m; ++i)
    {
        int t; cin>>t;
        flow.add_edge(s,i,t,0);
    }
    flow.add_edge(s,t,n,0);
    cout << accumulate(a.begin(),a.end(),0)-flow.min_cost_flow(s,t,n-k) << "\n";

}
accuracy: 0.1686746987951807
time_ms: 440
memory_kb: 3552
final_rank: 19

code_snippet: #include <bits/stdc++.h>

namespace std
{
    // hash
    template <class T> size_t hash_combine(size_t seed, T const &key) { return seed ^ (hash<T>()(key) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); }
    template <class T, class U> struct hash<pair<T, U>> { size_t operator()(pair<T, U> const &pr) const { return hash_combine(hash_combine(0, pr.first), pr.second); } };
    template <class tuple_t, size_t index = tuple_size<tuple_t>::value - 1> struct tuple_hash_calc { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(tuple_hash_calc<tuple_t, index - 1>::apply(seed, t), get<index>(t)); } };
    template <class tuple_t> struct tuple_hash_calc<tuple_t, 0> { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(seed, get<0>(t)); } };
    template <class... T> struct hash<tuple<T...>> { size_t operator()(tuple<T...> const &t) const { return tuple_hash_calc<tuple<T...>>::apply(0, t); } };
    // iostream
    template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) { return is >> p.first >> p.second; }
    template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { return os << p.first << ' ' << p.second; }
    template <class tuple_t, size_t index> struct tupleos { static ostream &apply(ostream &os, const tuple_t &t) { tupleos<tuple_t, index - 1>::apply(os, t); return os << ' ' << get<index>(t); } };
    template <class tuple_t> struct tupleos<tuple_t, 0> { static ostream &apply(ostream &os, const tuple_t &t) { return os << get<0>(t); } };
    template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t)  { return tupleos<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os, t); }
    template <> ostream &operator<<(ostream &os, const tuple<> &t) { return os; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    istream& operator>>(istream& is, Container &cont) { for(auto&& e : cont) is >> e; return is; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    ostream& operator<<(ostream& os, const Container &cont) { bool flag = 1; for(auto&& e : cont) flag ? flag = 0 : (os << ' ', 0), os << e; return os; }
} // namespace std


template <class cap_t, class cost_t>
struct Flow
{
    Flow(size_t _V) : V(_V), adj(_V) {}
    void add_edge(size_t from, size_t to, cap_t cap, cost_t cost = cost_t(0))
    {
        if(cap <= 0) return;
        adj[from].emplace_back(from, to, cap, cost, adj[to].size());
        adj[to].emplace_back(to, from, 0, -cost, adj[from].size() - 1);
    }
  protected:
    struct edge
    {
        size_t from, to; cap_t cap; cost_t cost; size_t rev;
        edge(size_t _from, size_t _to, cap_t _cap, cost_t _cost, size_t _rev) : from(_from), to(_to), cap(_cap), cost(_cost), rev(_rev) {}
    }; // struct edge
    size_t V;
    std::vector<std::vector<edge>> adj;
}; // struct Flow

template <class cap_t, class cost_t>
class Primal_Dual : public Flow<cap_t, cost_t>
{
    using edge = typename Flow<cap_t, cap_t>::edge;
    using Flow<cap_t, cap_t>::V; using Flow<cap_t, cap_t>::adj;
    bool neg_cost;
    std::vector<cost_t> dist, h;
    std::vector<size_t> prev_v;
    std::vector<edge*> prev_e;
    bool dijkstra(size_t s, size_t t)
    {
/*        using info = std::pair<cost_t, size_t>;
        std::priority_queue<info, std::vector<info>, std::greater<info>> que;
        fill(dist.begin(), dist.end(), inf_cost);
        que.emplace(dist[s] = 0, s);
        while(!que.empty())
        {
            cost_t _cost; size_t v;
            std::tie(_cost, v) = que.top(), que.pop();
            if(_cost != dist[v]) continue;
            for(auto &&e : adj[v])
            {
                if(e.cap > 0 && dist[v] + h[v] + e.cost < dist[e.to] + h[e.to])
                {
                    que.emplace(dist[e.to] = dist[v] + h[v] - h[e.to] + e.cost, e.to);
                    prev_v[e.to] = v;
                    prev_e[e.to] = &e;
                }
            }
        }
*/
        bool *used = new bool[V]{};
        for(fill(dist.begin(), dist.end(), inf_cost), dist[s] = 0; ; )
        {
            size_t nowv = -1;
            cost_t opt = inf_cost;
            for(size_t v = 0; v != V; ++v)
            {
                if(!used[v] && opt > dist[v])
                {
                    opt = dist[v];
                    nowv = v;
                }
            }
            if(nowv == -1) break;
            opt += h[nowv];
            used[nowv] = true;
            for(auto &&e : adj[nowv])
            {
                if(e.cap > 0 && dist[e.to] + h[e.to] > opt + e.cost)
                {
                    dist[e.to] = opt - h[e.to] + e.cost;
                    prev_v[e.to] = nowv;
                    prev_e[e.to] = &e;
                }
            }
        }
        delete[] used;

        if(dist[t] >= inf_cost) return false;
        for(size_t v = 0; v != V; ++v)
        {
            h[v] += dist[v];
            if(h[v] > inf_cost) h[v] = inf_cost;
        }
        return true;
    }
  public:
    const cost_t inf_cost = std::numeric_limits<cost_t>::max() / 4;
    Primal_Dual(size_t V) : Flow<cap_t, cost_t>(V), neg_cost() {}
    void add_edge(size_t s, size_t t, cap_t cap, cost_t cost)
    {
        if(cap <= 0) return;
        if(cost < 0) neg_cost = true;
        Flow<cap_t, cost_t>::add_edge(s, t, cap, cost);
    }
    cost_t min_cost_flow(size_t s, size_t t, cap_t f)
    {
        cost_t res = 0;
        if(neg_cost)
        {
            neg_cost = false;
            {
                const size_t _s = V++, _t = V++;
                adj.resize(V);
                add_edge(_s, s, f, 0);
                add_edge(t, _t, f, 0);
                s = _s, t = _t;
            }
            std::vector<cap_t> scap(V), tcap(V);
            for(size_t v = 0; v != V; ++v)
            {
                cap_t cap_sum = 0;
                for(auto &&e : adj[v])
                {
                    if(e.cap > 0 and e.cost < 0)
                    {
                        scap[e.to] += e.cap;
                        tcap[v] += e.cap;
                        res += e.cap * e.cost;
                        f += e.cap;
                        adj[e.to][e.rev].cap += e.cap;
                        cap_sum += e.cap;
                        e.cap = 0;
                    }
                }
            }
            for(size_t v = 0; v != V; ++v)
            {
                add_edge(s, v, scap[v], 0);
                add_edge(v, t, tcap[v], 0);
            }
        }
        dist.resize(V), h.assign(V, 0);
        prev_v.resize(V), prev_e.resize(V);
        while(f > 0)
        {
            if(!dijkstra(s, t)) return inf_cost;
            cap_t d = f;
            for(size_t v = t; v != s; v = prev_v[v]) d = std::min(d, prev_e[v]->cap);
            f -= d, res += h[t] * d;
            for(size_t v = t; v != s; v = prev_v[v])
            {
                prev_e[v]->cap -= d;
                adj[v][prev_e[v]->rev].cap += d;
            }
        }
        return res;
    }
}; // class Primal_Dual

main()
{
    using namespace std;
    int n,m,k; cin>>n>>m>>k;
    Primal_Dual<int,int> flow(2+n+m);
    vector<int> a(n); cin>>a;
    const int s=n+m,t=s+1;
    for(int i=0; i<m; ++i)
    {
        for(int j=0; j<n; ++j)
        {
            int b; cin>>b;
            flow.add_edge(i,j+m,1,-b);
        }
    }
    for(int i=m; i<m+n; ++i)
    {
        flow.add_edge(i,t,1,a[i-m]);
    }
    for(int i=0; i<m; ++i)
    {
        int t; cin>>t;
        flow.add_edge(s,i,t,0);
    }
    flow.add_edge(s,t,n,0);
    cout << accumulate(a.begin(),a.end(),0)-flow.min_cost_flow(s,t,n-k) << "\n";

}
accuracy: 1
time_ms: 1040
memory_kb: 3628
final_rank: 14

code_snippet: #include <bits/stdc++.h>

namespace std
{
    // hash
    template <class T> size_t hash_combine(size_t seed, T const &key) { return seed ^ (hash<T>()(key) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); }
    template <class T, class U> struct hash<pair<T, U>> { size_t operator()(pair<T, U> const &pr) const { return hash_combine(hash_combine(0, pr.first), pr.second); } };
    template <class tuple_t, size_t index = tuple_size<tuple_t>::value - 1> struct tuple_hash_calc { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(tuple_hash_calc<tuple_t, index - 1>::apply(seed, t), get<index>(t)); } };
    template <class tuple_t> struct tuple_hash_calc<tuple_t, 0> { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(seed, get<0>(t)); } };
    template <class... T> struct hash<tuple<T...>> { size_t operator()(tuple<T...> const &t) const { return tuple_hash_calc<tuple<T...>>::apply(0, t); } };
    // iostream
    template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) { return is >> p.first >> p.second; }
    template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { return os << p.first << ' ' << p.second; }
    template <class tuple_t, size_t index> struct tupleos { static ostream &apply(ostream &os, const tuple_t &t) { tupleos<tuple_t, index - 1>::apply(os, t); return os << ' ' << get<index>(t); } };
    template <class tuple_t> struct tupleos<tuple_t, 0> { static ostream &apply(ostream &os, const tuple_t &t) { return os << get<0>(t); } };
    template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t)  { return tupleos<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os, t); }
    template <> ostream &operator<<(ostream &os, const tuple<> &t) { return os; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    istream& operator>>(istream& is, Container &cont) { for(auto&& e : cont) is >> e; return is; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    ostream& operator<<(ostream& os, const Container &cont) { bool flag = 1; for(auto&& e : cont) flag ? flag = 0 : (os << ' ', 0), os << e; return os; }
} // namespace std


template <class cap_t, class cost_t>
struct Flow
{
    Flow(size_t _V) : V(_V), adj(_V) {}
    void add_edge(size_t from, size_t to, cap_t cap, cost_t cost = cost_t(0))
    {
        if(cap <= 0) return;
        adj[from].emplace_back(from, to, cap, cost, adj[to].size());
        adj[to].emplace_back(to, from, 0, -cost, adj[from].size() - 1);
    }
  protected:
    struct edge
    {
        size_t from, to; cap_t cap; cost_t cost; size_t rev;
        edge(size_t _from, size_t _to, cap_t _cap, cost_t _cost, size_t _rev) : from(_from), to(_to), cap(_cap), cost(_cost), rev(_rev) {}
    }; // struct edge
    size_t V;
    std::vector<std::vector<edge>> adj;
}; // struct Flow

template <class cap_t, class cost_t>
class Primal_Dual : public Flow<cap_t, cost_t>
{
    using edge = typename Flow<cap_t, cap_t>::edge;
    using Flow<cap_t, cap_t>::V; using Flow<cap_t, cap_t>::adj;
    bool neg_cost;
    std::vector<cost_t> dist, h;
    std::vector<size_t> prev_v;
    std::vector<edge*> prev_e;
    bool dijkstra(size_t s, size_t t)
    {
/*        using info = std::pair<cost_t, size_t>;
        std::priority_queue<info, std::vector<info>, std::greater<info>> que;
        fill(dist.begin(), dist.end(), inf_cost);
        que.emplace(dist[s] = 0, s);
        while(!que.empty())
        {
            cost_t _cost; size_t v;
            std::tie(_cost, v) = que.top(), que.pop();
            if(_cost != dist[v]) continue;
            for(auto &&e : adj[v])
            {
                if(e.cap > 0 && dist[v] + h[v] + e.cost < dist[e.to] + h[e.to])
                {
                    que.emplace(dist[e.to] = dist[v] + h[v] - h[e.to] + e.cost, e.to);
                    prev_v[e.to] = v;
                    prev_e[e.to] = &e;
                }
            }
        }
*/
        bool *used = new bool[V]{};
        for(fill(dist.begin(), dist.end(), inf_cost), dist[s] = 0; ; )
        {
            size_t nowv = -1;
            cost_t opt = inf_cost * 2;
            for(size_t v = 0; v != V; ++v)
            {
                if(!used[v] && opt > dist[v] + h[v])
                {
                    opt = dist[v] + h[v];
                    nowv = v;
                }
            }
            if(nowv == -1) break;
            used[nowv] = true;
            for(auto &&e : adj[nowv])
            {
                if(e.cap > 0 && dist[e.to] + h[e.to] > opt + e.cost)
                {
                    dist[e.to] = opt - h[e.to] + e.cost;
                    prev_v[e.to] = nowv;
                    prev_e[e.to] = &e;
                }
            }
        }
        delete[] used;

        if(dist[t] >= inf_cost) return false;
        for(size_t v = 0; v != V; ++v)
        {
            h[v] += dist[v];
            if(h[v] > inf_cost) h[v] = inf_cost;
        }
        return true;
    }
  public:
    const cost_t inf_cost = std::numeric_limits<cost_t>::max() / 4;
    Primal_Dual(size_t V) : Flow<cap_t, cost_t>(V), neg_cost() {}
    void add_edge(size_t s, size_t t, cap_t cap, cost_t cost)
    {
        if(cap <= 0) return;
        if(cost < 0) neg_cost = true;
        Flow<cap_t, cost_t>::add_edge(s, t, cap, cost);
    }
    cost_t min_cost_flow(size_t s, size_t t, cap_t f)
    {
        cost_t res = 0;
        if(neg_cost)
        {
            neg_cost = false;
            {
                const size_t _s = V++, _t = V++;
                adj.resize(V);
                add_edge(_s, s, f, 0);
                add_edge(t, _t, f, 0);
                s = _s, t = _t;
            }
            std::vector<cap_t> scap(V), tcap(V);
            for(size_t v = 0; v != V; ++v)
            {
                cap_t cap_sum = 0;
                for(auto &&e : adj[v])
                {
                    if(e.cap > 0 and e.cost < 0)
                    {
                        scap[e.to] += e.cap;
                        tcap[v] += e.cap;
                        res += e.cap * e.cost;
                        f += e.cap;
                        adj[e.to][e.rev].cap += e.cap;
                        cap_sum += e.cap;
                        e.cap = 0;
                    }
                }
            }
            for(size_t v = 0; v != V; ++v)
            {
                add_edge(s, v, scap[v], 0);
                add_edge(v, t, tcap[v], 0);
            }
        }
        dist.resize(V), h.assign(V, 0);
        prev_v.resize(V), prev_e.resize(V);
        while(f > 0)
        {
            if(!dijkstra(s, t)) return inf_cost;
            cap_t d = f;
            for(size_t v = t; v != s; v = prev_v[v]) d = std::min(d, prev_e[v]->cap);
            f -= d, res += h[t] * d;
            for(size_t v = t; v != s; v = prev_v[v])
            {
                prev_e[v]->cap -= d;
                adj[v][prev_e[v]->rev].cap += d;
            }
        }
        return res;
    }
}; // class Primal_Dual

main()
{
    using namespace std;
    int n,m,k; cin>>n>>m>>k;
    Primal_Dual<int,int> flow(2+n+m);
    vector<int> a(n); cin>>a;
    const int s=n+m,t=s+1;
    for(int i=0; i<m; ++i)
    {
        for(int j=0; j<n; ++j)
        {
            int b; cin>>b;
            flow.add_edge(i,j+m,1,-b);
        }
    }
    for(int i=m; i<m+n; ++i)
    {
        flow.add_edge(i,t,1,a[i-m]);
    }
    for(int i=0; i<m; ++i)
    {
        int t; cin>>t;
        flow.add_edge(s,i,t,0);
    }
    flow.add_edge(s,t,n,0);
    cout << accumulate(a.begin(),a.end(),0)-flow.min_cost_flow(s,t,n-k) << "\n";

}
accuracy: 0.1686746987951807
time_ms: 390
memory_kb: 3628
final_rank: 20

code_snippet: #include <bits/stdc++.h>

namespace std
{
    // hash
    template <class T> size_t hash_combine(size_t seed, T const &key) { return seed ^ (hash<T>()(key) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); }
    template <class T, class U> struct hash<pair<T, U>> { size_t operator()(pair<T, U> const &pr) const { return hash_combine(hash_combine(0, pr.first), pr.second); } };
    template <class tuple_t, size_t index = tuple_size<tuple_t>::value - 1> struct tuple_hash_calc { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(tuple_hash_calc<tuple_t, index - 1>::apply(seed, t), get<index>(t)); } };
    template <class tuple_t> struct tuple_hash_calc<tuple_t, 0> { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(seed, get<0>(t)); } };
    template <class... T> struct hash<tuple<T...>> { size_t operator()(tuple<T...> const &t) const { return tuple_hash_calc<tuple<T...>>::apply(0, t); } };
    // iostream
    template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) { return is >> p.first >> p.second; }
    template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { return os << p.first << ' ' << p.second; }
    template <class tuple_t, size_t index> struct tupleos { static ostream &apply(ostream &os, const tuple_t &t) { tupleos<tuple_t, index - 1>::apply(os, t); return os << ' ' << get<index>(t); } };
    template <class tuple_t> struct tupleos<tuple_t, 0> { static ostream &apply(ostream &os, const tuple_t &t) { return os << get<0>(t); } };
    template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t)  { return tupleos<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os, t); }
    template <> ostream &operator<<(ostream &os, const tuple<> &t) { return os; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    istream& operator>>(istream& is, Container &cont) { for(auto&& e : cont) is >> e; return is; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    ostream& operator<<(ostream& os, const Container &cont) { bool flag = 1; for(auto&& e : cont) flag ? flag = 0 : (os << ' ', 0), os << e; return os; }
} // namespace std


template <class cap_t, class cost_t>
struct Flow
{
    Flow(size_t _V) : V(_V), adj(_V) {}
    void add_edge(size_t from, size_t to, cap_t cap, cost_t cost = cost_t(0))
    {
        if(cap <= 0) return;
        adj[from].emplace_back(from, to, cap, cost, adj[to].size());
        adj[to].emplace_back(to, from, 0, -cost, adj[from].size() - 1);
    }
  protected:
    struct edge
    {
        size_t from, to; cap_t cap; cost_t cost; size_t rev;
        edge(size_t _from, size_t _to, cap_t _cap, cost_t _cost, size_t _rev) : from(_from), to(_to), cap(_cap), cost(_cost), rev(_rev) {}
    }; // struct edge
    size_t V;
    std::vector<std::vector<edge>> adj;
}; // struct Flow

template <class cap_t, class cost_t>
class Primal_Dual : public Flow<cap_t, cost_t>
{
    using edge = typename Flow<cap_t, cap_t>::edge;
    using Flow<cap_t, cap_t>::V; using Flow<cap_t, cap_t>::adj;
    bool neg_cost;
    std::vector<cost_t> dist, h;
    std::vector<size_t> prev_v;
    std::vector<edge*> prev_e;
    bool dijkstra(size_t s, size_t t)
    {
        using info = std::pair<cost_t, size_t>;
        std::priority_queue<info, std::vector<info>, std::greater<info>> que;
        fill(dist.begin(), dist.end(), inf_cost);
        que.emplace(dist[s] = 0, s);
        while(!que.empty())
        {
            cost_t _cost; size_t v;
            std::tie(_cost, v) = que.top(), que.pop();
            if(_cost != dist[v]) continue;
            for(auto &&e : adj[v])
            {
                if(e.cap > 0 && dist[v] + h[v] + e.cost < dist[e.to] + h[e.to])
                {
                    que.emplace(dist[e.to] = dist[v] + h[v] - h[e.to] + e.cost, e.to);
                    prev_v[e.to] = v;
                    prev_e[e.to] = &e;
                }
            }
        }
/*
        bool *used = new bool[V]{};
        for(fill(dist.begin(), dist.end(), inf_cost), dist[s] = 0; ; )
        {
            size_t nowv = -1;
            cost_t opt = inf_cost;
            for(size_t v = 0; v != V; ++v)
            {
                if(!used[v] && opt > dist[v] + h[v])
                {
                    opt = dist[v] + h[v];
                    nowv = v;
                }
            }
            if(nowv == -1) break;
            used[nowv] = true;
            for(auto &&e : adj[nowv])
            {
                if(e.cap > 0 && dist[e.to] + h[e.to] > opt + e.cost)
                {
                    dist[e.to] = opt - h[e.to] + e.cost;
                    prev_v[e.to] = nowv;
                    prev_e[e.to] = &e;
                }
            }
        }
        delete[] used;
*/
        if(dist[t] >= inf_cost) return false;
        for(size_t v = 0; v != V; ++v)
        {
            h[v] += dist[v];
            if(h[v] > inf_cost) h[v] = inf_cost;
        }
        return true;
    }
  public:
    const cost_t inf_cost = std::numeric_limits<cost_t>::max() / 4;
    Primal_Dual(size_t V) : Flow<cap_t, cost_t>(V), neg_cost() {}
    void add_edge(size_t s, size_t t, cap_t cap, cost_t cost)
    {
        if(cap <= 0) return;
        if(cost < 0) neg_cost = true;
        Flow<cap_t, cost_t>::add_edge(s, t, cap, cost);
    }
    cost_t min_cost_flow(size_t s, size_t t, cap_t f)
    {
        cost_t res = 0;
        if(neg_cost)
        {
            neg_cost = false;
            {
                const size_t _s = V++, _t = V++;
                adj.resize(V);
                add_edge(_s, s, f, 0);
                add_edge(t, _t, f, 0);
                s = _s, t = _t;
            }
            std::vector<cap_t> scap(V), tcap(V);
            for(size_t v = 0; v != V; ++v)
            {
                cap_t cap_sum = 0;
                for(auto &&e : adj[v])
                {
                    if(e.cap > 0 and e.cost < 0)
                    {
                        scap[e.to] += e.cap;
                        tcap[v] += e.cap;
                        res += e.cap * e.cost;
                        f += e.cap;
                        adj[e.to][e.rev].cap += e.cap;
                        cap_sum += e.cap;
                        e.cap = 0;
                    }
                }
            }
            for(size_t v = 0; v != V; ++v)
            {
                add_edge(s, v, scap[v], 0);
                add_edge(v, t, tcap[v], 0);
            }
        }
        dist.resize(V), h.assign(V, 0);
        prev_v.resize(V), prev_e.resize(V);
        while(f > 0)
        {
            if(!dijkstra(s, t)) return inf_cost;
            cap_t d = f;
            for(size_t v = t; v != s; v = prev_v[v]) d = std::min(d, prev_e[v]->cap);
            f -= d, res += h[t] * d;
            for(size_t v = t; v != s; v = prev_v[v])
            {
                prev_e[v]->cap -= d;
                adj[v][prev_e[v]->rev].cap += d;
            }
        }
        return res;
    }
}; // class Primal_Dual

main()
{
    using namespace std;
    int n,m,k; cin>>n>>m>>k;
    Primal_Dual<int,int> flow(2+n+m);
    vector<int> a(n); cin>>a;
    const int s=n+m,t=s+1;
    for(int i=0; i<m; ++i)
    {
        for(int j=0; j<n; ++j)
        {
            int b; cin>>b;
            flow.add_edge(i,j+m,1,-b);
        }
    }
    for(int i=m; i<m+n; ++i)
    {
        flow.add_edge(i,t,1,a[i-m]);
    }
    for(int i=0; i<m; ++i)
    {
        int t; cin>>t;
        flow.add_edge(s,i,t,0);
    }
    flow.add_edge(s,t,n,0);
    cout << accumulate(a.begin(),a.end(),0)-flow.min_cost_flow(s,t,n-k) << "\n";

}
accuracy: 1
time_ms: 710
memory_kb: 3760
final_rank: 12

code_snippet: #include <bits/stdc++.h>

namespace std
{
    // hash
    template <class T> size_t hash_combine(size_t seed, T const &key) { return seed ^ (hash<T>()(key) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); }
    template <class T, class U> struct hash<pair<T, U>> { size_t operator()(pair<T, U> const &pr) const { return hash_combine(hash_combine(0, pr.first), pr.second); } };
    template <class tuple_t, size_t index = tuple_size<tuple_t>::value - 1> struct tuple_hash_calc { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(tuple_hash_calc<tuple_t, index - 1>::apply(seed, t), get<index>(t)); } };
    template <class tuple_t> struct tuple_hash_calc<tuple_t, 0> { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(seed, get<0>(t)); } };
    template <class... T> struct hash<tuple<T...>> { size_t operator()(tuple<T...> const &t) const { return tuple_hash_calc<tuple<T...>>::apply(0, t); } };
    // iostream
    template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) { return is >> p.first >> p.second; }
    template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { return os << p.first << ' ' << p.second; }
    template <class tuple_t, size_t index> struct tupleos { static ostream &apply(ostream &os, const tuple_t &t) { tupleos<tuple_t, index - 1>::apply(os, t); return os << ' ' << get<index>(t); } };
    template <class tuple_t> struct tupleos<tuple_t, 0> { static ostream &apply(ostream &os, const tuple_t &t) { return os << get<0>(t); } };
    template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t)  { return tupleos<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os, t); }
    template <> ostream &operator<<(ostream &os, const tuple<> &t) { return os; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    istream& operator>>(istream& is, Container &cont) { for(auto&& e : cont) is >> e; return is; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    ostream& operator<<(ostream& os, const Container &cont) { bool flag = 1; for(auto&& e : cont) flag ? flag = 0 : (os << ' ', 0), os << e; return os; }
} // namespace std


template <class cap_t, class cost_t>
struct Flow
{
    Flow(size_t _V) : V(_V), adj(_V) {}
    void add_edge(size_t from, size_t to, cap_t cap, cost_t cost = cost_t(0))
    {
        if(cap <= 0) return;
        adj[from].emplace_back(from, to, cap, cost, adj[to].size());
        adj[to].emplace_back(to, from, 0, -cost, adj[from].size() - 1);
    }
  protected:
    struct edge
    {
        size_t from, to; cap_t cap; cost_t cost; size_t rev;
        edge(size_t _from, size_t _to, cap_t _cap, cost_t _cost, size_t _rev) : from(_from), to(_to), cap(_cap), cost(_cost), rev(_rev) {}
    }; // struct edge
    size_t V;
    std::vector<std::vector<edge>> adj;
}; // struct Flow

template <class cap_t, class cost_t>
class Primal_Dual : public Flow<cap_t, cost_t>
{
    using edge = typename Flow<cap_t, cap_t>::edge;
    using Flow<cap_t, cap_t>::V; using Flow<cap_t, cap_t>::adj;
    bool neg_cost;
    std::vector<cost_t> dist, h;
    std::vector<size_t> prev_v;
    std::vector<edge*> prev_e;
    bool dijkstra(size_t s, size_t t)
    {
        // using info = std::pair<cost_t, size_t>;
        // std::priority_queue<info, std::vector<info>, std::greater<info>> que;
        // fill(dist.begin(), dist.end(), inf_cost);
        // que.emplace(dist[s] = 0, s);
        // while(!que.empty())
        // {
        //     cost_t _cost; size_t v;
        //     std::tie(_cost, v) = que.top(), que.pop();
        //     if(_cost != dist[v]) continue;
        //     for(auto &&e : adj[v])
        //     {
        //         if(e.cap > 0 && dist[v] + h[v] + e.cost < dist[e.to] + h[e.to])
        //         {
        //             que.emplace(dist[e.to] = dist[v] + h[v] - h[e.to] + e.cost, e.to);
        //             prev_v[e.to] = v;
        //             prev_e[e.to] = &e;
        //         }
        //     }
        // }

        bool *used = new bool[V]{};
        for(fill(dist.begin(), dist.end(), inf_cost), dist[s] = 0; ; )
        {
            size_t nowv = -1;
            cost_t opt = inf_cost;
            for(size_t v = 0; v != V; ++v)
            {
                if(!used[v] && opt > dist[v] + h[v])
                {
                    opt = dist[v] + h[v];
                    nowv = v;
                }
            }
            if(nowv == -1) break;
            used[nowv] = true;
            for(auto &&e : adj[nowv])
            {
                if(e.cap > 0 && dist[e.to] + h[e.to] > opt + e.cost)
                {
                    dist[e.to] = opt - h[e.to] + e.cost;
                    prev_v[e.to] = nowv;
                    prev_e[e.to] = &e;
                }
            }
        }
        delete[] used;

        if(dist[t] >= inf_cost) return false;
        for(size_t v = 0; v != V; ++v)
        {
            h[v] += dist[v];
            if(h[v] > inf_cost) h[v] = inf_cost;
        }
        return true;
    }
  public:
    const cost_t inf_cost = std::numeric_limits<cost_t>::max() / 4;
    Primal_Dual(size_t V) : Flow<cap_t, cost_t>(V), neg_cost() {}
    void add_edge(size_t s, size_t t, cap_t cap, cost_t cost)
    {
        if(cap <= 0) return;
        if(cost < 0) neg_cost = true;
        Flow<cap_t, cost_t>::add_edge(s, t, cap, cost);
    }
    cost_t min_cost_flow(size_t s, size_t t, cap_t f)
    {
        cost_t res = 0;
        if(neg_cost)
        {
            neg_cost = false;
            {
                const size_t _s = V++, _t = V++;
                adj.resize(V);
                add_edge(_s, s, f, 0);
                add_edge(t, _t, f, 0);
                s = _s, t = _t;
            }
            std::vector<cap_t> scap(V), tcap(V);
            for(size_t v = 0; v != V; ++v)
            {
                cap_t cap_sum = 0;
                for(auto &&e : adj[v])
                {
                    if(e.cap > 0 and e.cost < 0)
                    {
                        scap[e.to] += e.cap;
                        tcap[v] += e.cap;
                        res += e.cap * e.cost;
                        f += e.cap;
                        adj[e.to][e.rev].cap += e.cap;
                        cap_sum += e.cap;
                        e.cap = 0;
                    }
                }
            }
            for(size_t v = 0; v != V; ++v)
            {
                add_edge(s, v, scap[v], 0);
                add_edge(v, t, tcap[v], 0);
            }
        }
        dist.resize(V), h.assign(V, 0);
        prev_v.resize(V), prev_e.resize(V);
        while(f > 0)
        {
            if(!dijkstra(s, t)) return inf_cost;
            cap_t d = f;
            for(size_t v = t; v != s; v = prev_v[v]) d = std::min(d, prev_e[v]->cap);
            f -= d, res += h[t] * d;
            for(size_t v = t; v != s; v = prev_v[v])
            {
                prev_e[v]->cap -= d;
                adj[v][prev_e[v]->rev].cap += d;
            }
        }
        return res;
    }
}; // class Primal_Dual

main()
{
    using namespace std;
    int n,m,k; cin>>n>>m>>k;
    Primal_Dual<int,int> flow(2+n+m);
    vector<int> a(n); cin>>a;
    const int s=n+m,t=s+1;
    for(int i=0; i<m; ++i)
    {
        for(int j=0; j<n; ++j)
        {
            int b; cin>>b;
            flow.add_edge(i,j+m,1,-b);
        }
    }
    for(int i=m; i<m+n; ++i)
    {
        flow.add_edge(i,t,1,a[i-m]);
    }
    for(int i=0; i<m; ++i)
    {
        int t; cin>>t;
        flow.add_edge(s,i,t,0);
    }
    flow.add_edge(s,t,n,0);
    cout << accumulate(a.begin(),a.end(),0)-flow.min_cost_flow(s,t,n-k) << "\n";

}
accuracy: 0.1686746987951807
time_ms: 400
memory_kb: 3568
final_rank: 18

code_snippet: #include <bits/stdc++.h>

namespace std
{
    // hash
    template <class T> size_t hash_combine(size_t seed, T const &key) { return seed ^ (hash<T>()(key) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); }
    template <class T, class U> struct hash<pair<T, U>> { size_t operator()(pair<T, U> const &pr) const { return hash_combine(hash_combine(0, pr.first), pr.second); } };
    template <class tuple_t, size_t index = tuple_size<tuple_t>::value - 1> struct tuple_hash_calc { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(tuple_hash_calc<tuple_t, index - 1>::apply(seed, t), get<index>(t)); } };
    template <class tuple_t> struct tuple_hash_calc<tuple_t, 0> { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(seed, get<0>(t)); } };
    template <class... T> struct hash<tuple<T...>> { size_t operator()(tuple<T...> const &t) const { return tuple_hash_calc<tuple<T...>>::apply(0, t); } };
    // iostream
    template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) { return is >> p.first >> p.second; }
    template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { return os << p.first << ' ' << p.second; }
    template <class tuple_t, size_t index> struct tupleos { static ostream &apply(ostream &os, const tuple_t &t) { tupleos<tuple_t, index - 1>::apply(os, t); return os << ' ' << get<index>(t); } };
    template <class tuple_t> struct tupleos<tuple_t, 0> { static ostream &apply(ostream &os, const tuple_t &t) { return os << get<0>(t); } };
    template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t)  { return tupleos<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os, t); }
    template <> ostream &operator<<(ostream &os, const tuple<> &t) { return os; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    istream& operator>>(istream& is, Container &cont) { for(auto&& e : cont) is >> e; return is; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    ostream& operator<<(ostream& os, const Container &cont) { bool flag = 1; for(auto&& e : cont) flag ? flag = 0 : (os << ' ', 0), os << e; return os; }
} // namespace std


template <class cap_t, class cost_t>
struct Flow
{
    Flow(size_t _V) : V(_V), adj(_V) {}
    void add_edge(size_t from, size_t to, cap_t cap, cost_t cost = cost_t(0))
    {
        if(cap <= 0) return;
        adj[from].emplace_back(from, to, cap, cost, adj[to].size());
        adj[to].emplace_back(to, from, 0, -cost, adj[from].size() - 1);
    }
  protected:
    struct edge
    {
        size_t from, to; cap_t cap; cost_t cost; size_t rev;
        edge(size_t _from, size_t _to, cap_t _cap, cost_t _cost, size_t _rev) : from(_from), to(_to), cap(_cap), cost(_cost), rev(_rev) {}
    }; // struct edge
    size_t V;
    std::vector<std::vector<edge>> adj;
}; // struct Flow

template <class cap_t, class cost_t>
class Primal_Dual : public Flow<cap_t, cost_t>
{
    using edge = typename Flow<cap_t, cap_t>::edge;
    using Flow<cap_t, cap_t>::V; using Flow<cap_t, cap_t>::adj;
    bool neg_cost;
    std::vector<cost_t> dist, h;
    std::vector<size_t> prev_v;
    std::vector<edge*> prev_e;
    bool dijkstra(size_t s, size_t t)
    {
        using info = std::pair<cost_t, size_t>;
        std::priority_queue<info, std::vector<info>, std::greater<info>> que;
        fill(dist.begin(), dist.end(), inf_cost);
        que.emplace(dist[s] = 0, s);
        while(!que.empty())
        {
            cost_t _cost; size_t v;
            std::tie(_cost, v) = que.top(), que.pop();
            if(_cost != dist[v]) continue;
            for(auto &&e : adj[v])
            {
                if(e.cap > 0 && dist[v] + h[v] + e.cost < dist[e.to] + h[e.to])
                {
                    que.emplace(dist[e.to] = dist[v] + h[v] - h[e.to] + e.cost, e.to);
                    prev_v[e.to] = v;
                    prev_e[e.to] = &e;
                }
            }
        }
        if(dist[t] >= inf_cost) return false;
        for(size_t v = 0; v != V; ++v)
        {
            h[v] += dist[v];
            if(h[v] > inf_cost) h[v] = inf_cost;
        }
        return true;
    }
  public:
    const cost_t inf_cost = std::numeric_limits<cost_t>::max() / 4;
    Primal_Dual(size_t V) : Flow<cap_t, cost_t>(V), neg_cost() {}
    void add_edge(size_t s, size_t t, cap_t cap, cost_t cost)
    {
        if(cap <= 0) return;
        if(cost < 0) neg_cost = true;
        Flow<cap_t, cost_t>::add_edge(s, t, cap, cost);
    }
    cost_t min_cost_flow(size_t s, size_t t, cap_t f)
    {
        cost_t res = 0;
        if(neg_cost)
        {
            neg_cost = false;
            {
                const size_t _s = V++, _t = V++;
                adj.resize(V);
                add_edge(_s, s, f, 0);
                add_edge(t, _t, f, 0);
                s = _s, t = _t;
            }
            std::vector<cap_t> scap(V), tcap(V);
            for(size_t v = 0; v != V; ++v)
            {
                cap_t cap_sum = 0;
                for(auto &&e : adj[v])
                {
                    if(e.cap > 0 and e.cost < 0)
                    {
                        scap[e.to] += e.cap;
                        tcap[v] += e.cap;
                        res += e.cap * e.cost;
                        f += e.cap;
                        adj[e.to][e.rev].cap += e.cap;
                        cap_sum += e.cap;
                        e.cap = 0;
                    }
                }
            }
            for(size_t v = 0; v != V; ++v)
            {
                add_edge(s, v, scap[v], 0);
                add_edge(v, t, tcap[v], 0);
            }
        }
        dist.resize(V), h.assign(V, 0);
        prev_v.resize(V), prev_e.resize(V);
        while(f > 0)
        {
            if(!dijkstra(s, t)) return inf_cost;
            cap_t d = f;
            for(int v = t; v != s; v = prev_v[v]) d = std::min(d, prev_e[v]->cap);
            f -= d, res += h[t] * d;
            for(int v = t; v != s; v = prev_v[v])
            {
                prev_e[v]->cap -= d;
                adj[v][prev_e[v]->rev].cap += d;
            }
        }
        return res;
    }
}; // class Primal_Dual

main()
{
    using namespace std;
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    int n,m,k; cin>>n>>m>>k;
    Primal_Dual<int,int> flow(2+n+m);
    vector<int> a(n); cin>>a;
    const int s=n+m,t=s+1;
    for(int i=0; i<m; ++i)
    {
        for(int j=0; j<n; ++j)
        {
            int b; cin>>b;
            flow.add_edge(i,j+m,1,-b);
        }
    }
    for(int i=m; i<m+n; ++i)
    {
        flow.add_edge(i,t,1,a[i-m]);
    }
    for(int i=0; i<m; ++i)
    {
        int t; cin>>t;
        flow.add_edge(s,i,t,0);
    }
    flow.add_edge(s,t,n,0);
    cout << accumulate(a.begin(),a.end(),0)-flow.min_cost_flow(s,t,n-k) << "\n";
}
accuracy: 1
time_ms: 680
memory_kb: 3724
final_rank: 11

code_snippet: #include <bits/stdc++.h>

namespace std
{
    // hash
    template <class T> size_t hash_combine(size_t seed, T const &key) { return seed ^ (hash<T>()(key) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); }
    template <class T, class U> struct hash<pair<T, U>> { size_t operator()(pair<T, U> const &pr) const { return hash_combine(hash_combine(0, pr.first), pr.second); } };
    template <class tuple_t, size_t index = tuple_size<tuple_t>::value - 1> struct tuple_hash_calc { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(tuple_hash_calc<tuple_t, index - 1>::apply(seed, t), get<index>(t)); } };
    template <class tuple_t> struct tuple_hash_calc<tuple_t, 0> { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(seed, get<0>(t)); } };
    template <class... T> struct hash<tuple<T...>> { size_t operator()(tuple<T...> const &t) const { return tuple_hash_calc<tuple<T...>>::apply(0, t); } };
    // iostream
    template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) { return is >> p.first >> p.second; }
    template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { return os << p.first << ' ' << p.second; }
    template <class tuple_t, size_t index> struct tupleos { static ostream &apply(ostream &os, const tuple_t &t) { tupleos<tuple_t, index - 1>::apply(os, t); return os << ' ' << get<index>(t); } };
    template <class tuple_t> struct tupleos<tuple_t, 0> { static ostream &apply(ostream &os, const tuple_t &t) { return os << get<0>(t); } };
    template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t)  { return tupleos<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os, t); }
    template <> ostream &operator<<(ostream &os, const tuple<> &t) { return os; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    istream& operator>>(istream& is, Container &cont) { for(auto&& e : cont) is >> e; return is; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    ostream& operator<<(ostream& os, const Container &cont) { bool flag = 1; for(auto&& e : cont) flag ? flag = 0 : (os << ' ', 0), os << e; return os; }
} // namespace std


template <class cap_t, class cost_t>
struct Flow
{
    Flow(size_t _V) : V(_V), adj(_V) {}
    void add_edge(size_t from, size_t to, cap_t cap, cost_t cost = cost_t(0))
    {
        if(cap <= 0) return;
        adj[from].emplace_back(from, to, cap, cost, adj[to].size());
        adj[to].emplace_back(to, from, 0, -cost, adj[from].size() - 1);
    }
  protected:
    struct edge
    {
        size_t from, to; cap_t cap; cost_t cost; size_t rev;
        edge(size_t _from, size_t _to, cap_t _cap, cost_t _cost, size_t _rev) : from(_from), to(_to), cap(_cap), cost(_cost), rev(_rev) {}
    }; // struct edge
    size_t V;
    std::vector<std::vector<edge>> adj;
}; // struct Flow

template <class cap_t, class cost_t>
class Primal_Dual : public Flow<cap_t, cost_t>
{
    using edge = typename Flow<cap_t, cap_t>::edge;
    using Flow<cap_t, cap_t>::V; using Flow<cap_t, cap_t>::adj;
    bool neg_cost;
    std::vector<cost_t> dist, h;
    std::vector<size_t> prev_v;
    std::vector<edge*> prev_e;
    bool dijkstra(size_t s, size_t t)
    {
        using info = std::pair<cost_t, size_t>;
        std::priority_queue<info, std::vector<info>, std::greater<info>> que;
        fill(dist.begin(), dist.end(), inf_cost);
        que.emplace(dist[s] = 0, s);
        while(!que.empty())
        {
            cost_t _cost; size_t v;
            std::tie(_cost, v) = que.top(), que.pop();
            if(_cost != dist[v]) continue;
            for(auto &&e : adj[v])
            {
                if(e.cap > 0 && dist[v] + h[v] + e.cost < dist[e.to] + h[e.to])
                {
                    que.emplace(dist[e.to] = dist[v] + h[v] - h[e.to] + e.cost, e.to);
                    prev_v[e.to] = v;
                    prev_e[e.to] = &e;
                }
            }
        }
        if(dist[t] >= inf_cost) return false;
        for(size_t v = 0; v != V; ++v)
        {
            h[v] += dist[v];
            if(h[v] > inf_cost) h[v] = inf_cost;
        }
        return true;
    }
  public:
    const cost_t inf_cost = std::numeric_limits<cost_t>::max() / 4;
    Primal_Dual(size_t V) : Flow<cap_t, cost_t>(V), neg_cost() {}
    void add_edge(size_t s, size_t t, cap_t cap, cost_t cost)
    {
        if(cap <= 0) return;
        if(cost < 0) neg_cost = true;
        Flow<cap_t, cost_t>::add_edge(s, t, cap, cost);
    }
    cost_t min_cost_flow(size_t s, size_t t, cap_t f)
    {
        cost_t res = 0;
        if(neg_cost)
        {
            neg_cost = false;
            {
                const size_t _s = V++, _t = V++;
                adj.resize(V);
                add_edge(_s, s, f, 0);
                add_edge(t, _t, f, 0);
                s = _s, t = _t;
            }
            std::vector<cap_t> scap(V), tcap(V);
            for(size_t v = 0; v != V; ++v)
            {
                cap_t cap_sum = 0;
                for(auto &&e : adj[v])
                {
                    if(e.cap > 0 and e.cost < 0)
                    {
                        scap[e.to] += e.cap;
                        tcap[v] += e.cap;
                        res += e.cap * e.cost;
                        f += e.cap;
                        adj[e.to][e.rev].cap += e.cap;
                        cap_sum += e.cap;
                        e.cap = 0;
                    }
                }
            }
            for(size_t v = 0; v != V; ++v)
            {
                add_edge(s, v, scap[v], 0);
                add_edge(v, t, tcap[v], 0);
            }
        }
        dist.resize(V), h.assign(V, 0);
        prev_v.resize(V), prev_e.resize(V);
        while(f > 0)
        {
            if(!dijkstra(s, t)) return inf_cost;
            cap_t d = f;
            for(int v = t; v != s; v = prev_v[v]) d = std::min(d, prev_e[v]->cap);
            f -= d, res += h[t] * d;
            for(int v = t; v != s; v = prev_v[v])
            {
                prev_e[v]->cap -= d;
                adj[v][prev_e[v]->rev].cap += d;
            }
        }
        return res;
    }
}; // class Primal_Dual

main()
{
    using namespace std;
    int n,m,k; cin>>n>>m>>k;
    Primal_Dual<int,int> flow(2+n+m);
    vector<int> a(n); cin>>a;
    const int s=n+m,t=s+1;
    for(int i=0; i<m; ++i)
    {
        for(int j=0; j<n; ++j)
        {
            int b; cin>>b;
            flow.add_edge(i,j+m,1,-b);
        }
    }
    for(int i=m; i<m+n; ++i)
    {
        flow.add_edge(i,t,1,a[i-m]);
    }
    for(int i=0; i<m; ++i)
    {
        int t; cin>>t;
        flow.add_edge(s,i,t,0);
    }
    flow.add_edge(s,t,n,0);
    cout << accumulate(a.begin(),a.end(),0)-flow.min_cost_flow(s,t,n-k) << "\n";
}
accuracy: 1
time_ms: 690
memory_kb: 3692
final_rank: 9

code_snippet: #include <bits/stdc++.h>

namespace std
{
    // hash
    template <class T> size_t hash_combine(size_t seed, T const &key) { return seed ^ (hash<T>()(key) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); }
    template <class T, class U> struct hash<pair<T, U>> { size_t operator()(pair<T, U> const &pr) const { return hash_combine(hash_combine(0, pr.first), pr.second); } };
    template <class tuple_t, size_t index = tuple_size<tuple_t>::value - 1> struct tuple_hash_calc { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(tuple_hash_calc<tuple_t, index - 1>::apply(seed, t), get<index>(t)); } };
    template <class tuple_t> struct tuple_hash_calc<tuple_t, 0> { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(seed, get<0>(t)); } };
    template <class... T> struct hash<tuple<T...>> { size_t operator()(tuple<T...> const &t) const { return tuple_hash_calc<tuple<T...>>::apply(0, t); } };
    // iostream
    template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) { return is >> p.first >> p.second; }
    template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { return os << p.first << ' ' << p.second; }
    template <class tuple_t, size_t index> struct tupleos { static ostream &apply(ostream &os, const tuple_t &t) { tupleos<tuple_t, index - 1>::apply(os, t); return os << ' ' << get<index>(t); } };
    template <class tuple_t> struct tupleos<tuple_t, 0> { static ostream &apply(ostream &os, const tuple_t &t) { return os << get<0>(t); } };
    template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t)  { return tupleos<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os, t); }
    template <> ostream &operator<<(ostream &os, const tuple<> &t) { return os; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    istream& operator>>(istream& is, Container &cont) { for(auto&& e : cont) is >> e; return is; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    ostream& operator<<(ostream& os, const Container &cont) { bool flag = 1; for(auto&& e : cont) flag ? flag = 0 : (os << ' ', 0), os << e; return os; }
} // namespace std


template <class cap_t, class cost_t>
struct Flow
{
    Flow(size_t _V) : V(_V), adj(_V) {}
    void add_edge(size_t from, size_t to, cap_t cap, cost_t cost = cost_t(0))
    {
        if(cap <= 0) return;
        adj[from].emplace_back(from, to, cap, cost, adj[to].size());
        adj[to].emplace_back(to, from, 0, -cost, adj[from].size() - 1);
    }
  protected:
    struct edge
    {
        size_t from, to; cap_t cap; cost_t cost; size_t rev;
        edge(size_t _from, size_t _to, cap_t _cap, cost_t _cost, size_t _rev) : from(_from), to(_to), cap(_cap), cost(_cost), rev(_rev) {}
    }; // struct edge
    size_t V;
    std::vector<std::vector<edge>> adj;
}; // struct Flow

template <class cap_t, class cost_t>
class Primal_Dual : public Flow<cap_t, cost_t>
{
    using edge = typename Flow<cap_t, cap_t>::edge;
    using Flow<cap_t, cap_t>::V; using Flow<cap_t, cap_t>::adj;
    bool neg_cost;
    std::vector<cost_t> dist, h;
    std::vector<size_t> prev_v;
    std::vector<edge*> prev_e;
    bool dijkstra(size_t s, size_t t)
    {
        using info = std::pair<cost_t, size_t>;
        std::priority_queue<info, std::vector<info>, std::greater<info>> que;
        fill(dist.begin(), dist.end(), inf_cost);
        que.emplace(dist[s] = 0, s);
        while(!que.empty())
        {
            cost_t _cost; size_t v;
            std::tie(_cost, v) = que.top(), que.pop();
            if(_cost != dist[v]) continue;
            for(auto &&e : adj[v])
            {
                if(e.cap > 0 && dist[v] + h[v] + e.cost < dist[e.to] + h[e.to])
                {
                    que.emplace(dist[e.to] = dist[v] + h[v] - h[e.to] + e.cost, e.to);
                    prev_v[e.to] = v;
                    prev_e[e.to] = &e;
                }
            }
        }
        if(dist[t] >= inf_cost) return false;
        for(size_t v = 0; v != V; ++v)
        {
            h[v] += dist[v];
            if(h[v] > inf_cost) h[v] = inf_cost;
        }
        return true;
    }
  public:
    const cost_t inf_cost = std::numeric_limits<cost_t>::max() / 4;
    Primal_Dual(size_t V) : Flow<cap_t, cost_t>(V), neg_cost() {}
    void add_edge(size_t s, size_t t, cap_t cap, cost_t cost)
    {
        if(cap <= 0) return;
        if(cost < 0) neg_cost = true;
        Flow<cap_t, cost_t>::add_edge(s, t, cap, cost);
    }
    cost_t min_cost_flow(size_t s, size_t t, cap_t f)
    {
        cost_t res = 0;
        if(neg_cost)
        {
            neg_cost = false;
            {
                const size_t _s = V++, _t = V++;
                adj.resize(V);
                add_edge(_s, s, f, 0);
                add_edge(t, _t, f, 0);
                s = _s, t = _t;
            }
            for(size_t v = 0; v != V; ++v)
            {
                cap_t cap_sum = 0;
                for(auto &&e : adj[v])
                {
                    if(e.cap > 0 and e.cost < 0)
                    {
                        add_edge(s, e.to, e.cap, 0);
                        res += e.cap * e.cost;
                        f += e.cap;
                        adj[e.to][e.rev].cap += e.cap;
                        cap_sum += e.cap;
                        e.cap = 0;
                    }
                }
                add_edge(v, t, cap_sum, 0);
            }
        }
        dist.resize(V), h.assign(V, 0);
        prev_v.resize(V), prev_e.resize(V);
        while(f > 0)
        {
            if(!dijkstra(s, t)) return inf_cost;
            cap_t d = f;
            for(int v = t; v != s; v = prev_v[v]) d = std::min(d, prev_e[v]->cap);
            f -= d, res += h[t] * d;
            for(int v = t; v != s; v = prev_v[v])
            {
                prev_e[v]->cap -= d;
                adj[v][prev_e[v]->rev].cap += d;
            }
        }
        return res;
    }
}; // class Primal_Dual

main()
{
    using namespace std;
    int n,m,k; cin>>n>>m>>k;
    Primal_Dual<int,int> flow(2+n+m);
    vector<int> a(n); cin>>a;
    const int s=n+m,t=s+1;
    for(int i=0; i<m; ++i)
    {
        for(int j=0; j<n; ++j)
        {
            int b; cin>>b;
            flow.add_edge(i,j+m,1,-b);
        }
    }
    for(int i=m; i<m+n; ++i)
    {
        flow.add_edge(i,t,1,a[i-m]);
    }
    for(int i=0; i<m; ++i)
    {
        int t; cin>>t;
        flow.add_edge(s,i,t,0);
    }
    flow.add_edge(s,t,n,0);
    cout << accumulate(a.begin(),a.end(),0)-flow.min_cost_flow(s,t,n-k) << "\n";
}
accuracy: 1
time_ms: 970
memory_kb: 4616
final_rank: 17

code_snippet: #include "bits/stdc++.h"
using namespace std;
typedef long long ll;
const ll MOD = 1e9 + 7;
using PII = pair<ll, ll>;
#define FOR(i,a,n) for(ll i=(ll)a; i<(ll)n; ++i)
#define REP(i,n) FOR(i,0,n)
const ll INF = 1LL << 60;
template<typename T> void chmin(T &a, T b) { a = min(a, b); }

struct min_cost_max_flow {
	struct edge {
		int to;
		ll cap, cost;
		int rev;
		bool isrev;
	};

	int n, s, t;
	ll neg;
	vector<vector<edge>> g;
	vector<ll> d, h, dist, prevv, preve;

	ll flow(vector<ll> d0) {
		ll res = 0;
		priority_queue<PII, vector<PII>, greater<PII>> que;
		h.assign(n, 0);
		preve.assign(n, -1);
		prevv.assign(n, -1);
		ll f = 0;
		REP(i, d.size()) {
			if (i < (ll)d0.size()) d[i] += d0[i];
			if (d[i] > 0) add_edge(s, i, d[i], 0), f += d[i];
			else if (d[i] < 0) add_edge(i, t, -d[i], 0);
		}
		while (f > 0) {
			dist.assign(n, INF);
			dist[s] = 0;
			que.push({ 0, s });
			while (que.size()) {
				PII p = que.top(); que.pop();
				int v = p.second;
				if (dist[v] < p.first) continue;
				REP(i, g[v].size()) {
					edge &e = g[v][i];
					if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
						dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
						prevv[e.to] = v;
						preve[e.to] = i;
						que.push({ dist[e.to], e.to });
					}
				}
			}
			if (dist[t] == INF) return -1;
			REP(v, n) h[v] += dist[v];
			ll d = f;
			for (int v = t; v != s; v = prevv[v]) {
				chmin(d, g[prevv[v]][preve[v]].cap);
			}
			f -= d; res += d * h[t];
			for (int v = t; v != s; v = prevv[v]) {
				edge &e = g[prevv[v]][preve[v]];
				e.cap -= d;
				g[v][e.rev].cap += d;
			}
		}
		return neg + res;
	} 

	min_cost_max_flow(int n0) : n(n0+2), s(n0), t(n0+1), neg(0), g(n0+2), d(n0+2) {}

	void add_edge(int from, int to, ll cap, ll cost) {
		if (cost >= 0) {
			g[from].push_back({ to, cap, cost, (int)g[to].size(), false });
			g[to].push_back({ from, 0, -cost, (int)g[from].size() - 1, true });
		}
		else {
			d[from] -= cap;
			d[to] += cap;
			neg += cap * cost;
			add_edge(to, from, cap, -cost);
		}
	}

	ll flow(int S, int T, ll f) {
		vector<ll> d0(n);
		d0[S] = f, d0[T] = -f;
		return flow(d0);
	}
};

int main() {
	ll n, m, k;
	cin >> n >> m >> k;
	vector<ll> a(n), T(m);
	vector<vector<ll>> b(m, vector<ll>(n));
	REP(i, n) cin >> a[i];
	REP(i, m) REP(j, n) cin >> b[i][j];
	REP(i, m) cin >> T[i];

	min_cost_max_flow graph(n + m + 4);
	ll s = n + m + 2, t = n + m + 3, x = n + m, y = n + m + 1;
	graph.add_edge(s, x, n, 0);
	graph.add_edge(s, y, n-k, 0);
	REP(i, m) graph.add_edge(y, i, T[i], 0);
	REP(i, n) graph.add_edge(m + i, t, 1, 0);
	REP(i, n) graph.add_edge(x, m + i, 1, -a[i]);
	REP(i, m) REP(j, n) graph.add_edge(i, m + j, 1, -b[i][j]);

	cout << -graph.flow(s, t, n) << endl;
}
accuracy: 1
time_ms: 840
memory_kb: 3968
final_rank: 16

code_snippet: #include<iostream>
#include<vector>
#include<queue>
#define loop(i,a,b) for(int i=a;i<b;i++)
#define rep(i,a) loop(i,0,a)
#define pb push_back
using namespace std;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
const int inf=1e8;
struct edge{
    int to,cap,cost,rev;
};
typedef vector<edge> ve;
typedef vector<ve> vve;
class MCF{    //Minimum Cost Flow
public:
    int n;
    vve G;
    vi h,dist,prev,pree;
    MCF(int size){
        n=size;
        G=vve(n);
        h=dist=prev=pree=vi(n);
    }
    void add_edge(int s,int t,int ca,int co){
        edge e={t,ca,co,(int)G[t].size()};
        G[s].pb(e);
        edge ee={s,0,-co,(int)G[s].size()-1};
        G[t].pb(ee);
    }
    int mcf(int s,int t,int f){
        int out=0;
        h=vi(n);
        while(f>0){
            priority_queue<pii,vector<pii> >q;
            dist=vi(n,inf);
            dist[s]=0;
            q.push(pii(0,s));
            while(!q.empty()){
                pii p=q.top();q.pop();
                int v=p.second;
                if(dist[v]<-p.first)continue;
                rep(i,G[v].size()){
                    edge &e=G[v][i];
                    if(e.cap>0&&dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]){
                        dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];
                        prev[e.to]=v;
                        pree[e.to]=i;
                        q.push(pii(-dist[e.to],e.to));
                    }
                }
            }
            if(dist[t]==inf)return -1;
            rep(i,n)h[i]+=dist[i];
            int d=f;
            for(int v=t;v!=s;v=prev[v])d=min(d,G[prev[v]][pree[v]].cap);
            f-=d;
            out+=d*h[t];
            for(int v=t;v!=s;v=prev[v]){
                edge &e=G[prev[v]][pree[v]];
                e.cap-=d;
                G[v][e.rev].cap+=d;
            }
        }
        return out;
    }
};
signed main(){
    //n個のレポート, m人の友だち
    
    int n,m,k; cin >> n >> m >> k;
    vector<vector<int>>v(m+1,vector<int>(n));
    rep(i,m+1)rep(j,n) cin >> v[i][j];
    vector<int>frd;
    frd.push_back(n);
    rep(i,m){
        int tmp; cin >> tmp;
        frd.push_back(tmp);
    }
    MCF fl(n+m+5);
    //fl.add_edge(int s, int t, int cap, int cost)
    int source = n+m+5 - 2;
    int sink = n+m+5-1;
    int fri = source-1;
    int msl = fri - 1;
    fl.add_edge(msl, sink, n, 0);
    fl.add_edge(fri, sink, n-k, 0);
    //各レポートに辺を貼る
    rep(i,n)fl.add_edge(source,i, 1, 0);
    rep(i,n)rep(j,m+1){
        fl.add_edge(i,n+j,1, 1000-v[j][i]);
    }
    rep(i,m+1){
        fl.add_edge(n+i, (i!=0?fri:msl),frd[i],0);
    }
    cout << 1000*n-fl.mcf(source, sink, n) << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3388
final_rank: 1

code_snippet: #include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 250


//辺を表す構造体{行先、容量、コスト、逆辺のインデックス}
struct Edge{
	Edge(int arg_to,int arg_capacity,int arg_cost,int arg_rev_index){
		to = arg_to;
		capacity = arg_capacity;
		cost = arg_cost;
		rev_index = arg_rev_index;
	}

	int to,capacity,cost,rev_index;
};

int V; //頂点数
vector<Edge> G[NUM]; //グラフの隣接リスト表現
int dist[NUM]; //最短距離
int pre_node[NUM],pre_edge[NUM]; //直前の頂点と辺
int A[101],B[101][101],T[101];


//fromからtoへ向かう容量capacity,コストcostの辺をグラフに追加する
void add_edge(int from,int to,int capacity,int cost){
	G[from].push_back(Edge(to,capacity,cost,G[to].size()));
	G[to].push_back(Edge(from,0,-cost,G[from].size()-1));
}

//sourceからsinkへの、流量flowの最小費用流を求める
//流せない場合は-1を返す
int min_cost_flow(int source,int sink,int flow){
	int ret = 0;
	while(flow > 0){
		//ベルマンフォード方により、source-sink間最短経路を求める
		for(int i = 0; i < V; i++)dist[i] = BIG_NUM;
		dist[source] = 0;
		bool update = true;
		while(update){
			update = false;
			for(int node_id = 0; node_id < V; node_id++){
				if(dist[node_id] == BIG_NUM)continue;
				for(int i = 0; i < G[node_id].size(); i++){
					Edge &e = G[node_id][i];
					if(e.capacity > 0 && dist[e.to] > dist[node_id]+e.cost){
						dist[e.to] = dist[node_id]+e.cost; //node_idを経由した方が早い場合
						pre_node[e.to] = node_id;
						pre_edge[e.to] = i;
						update = true;
					}
				}
			}
		}

		if(dist[sink] == BIG_NUM){
			//これ以上流せない
			return -1;
		}

		//source-sink間最短路に沿って目いっぱい流す
		int tmp_flow = flow;
		for(int node_id = sink; node_id != source; node_id = pre_node[node_id]){
			tmp_flow = min(tmp_flow,G[pre_node[node_id]][pre_edge[node_id]].capacity);
		}
		flow -= tmp_flow;
		ret += tmp_flow*dist[sink];
		for(int node_id = sink; node_id != source; node_id = pre_node[node_id]){
			Edge &e = G[pre_node[node_id]][pre_edge[node_id]];
			e.capacity -= tmp_flow;
			G[node_id][e.rev_index].capacity += tmp_flow;
		}
	}
	return ret;
}

int main(){

	int N,M,K;
	scanf("%d %d %d",&N,&M,&K);

	for(int i = 0; i < N; i++)scanf("%d",&A[i]);

	for(int i = 0; i < M; i++){
		for(int k = 0; k < N; k++)scanf("%d",&B[i][k]);
	}

	for(int i = 0; i < M; i++)scanf("%d",&T[i]);

	int source = 0,sink = 1,first_branch = 2,second_branch = 3,me = 4,index = 5;

	add_edge(source,first_branch,N,0); //全体の流量をNに設定する
	add_edge(first_branch,me,N,0); //自分に最大N流せるようにする
	add_edge(first_branch,second_branch,N-K,0); //最大でも友達にはN-Kしか流せないようにする

	int friend_index[M],report_index[N];

	for(int i = 0; i < M; i++){
		friend_index[i] = index++;
		add_edge(second_branch,friend_index[i],T[i],0); //友達iに流量T[i]の辺を張る
	}

	for(int i = 0; i < N; i++){
		report_index[i] = index++;
		add_edge(report_index[i],sink,1,0); //レポートからsinkへ辺を張る
	}

	for(int i = 0; i < N; i++){
		add_edge(me,report_index[i],1,-A[i]); //自分からレポートに、負のコストの辺を張る
	}

	for(int i = 0; i < M; i++){
		for(int k = 0; k < N; k++){
			add_edge(friend_index[i],report_index[k],1,-B[i][k]); //友達iからレポートkに、負のコストの辺を張る
		}
	}

	V = index;

	printf("%d\n",-min_cost_flow(source,sink,N));

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3476
final_rank: 4

code_snippet: #include <bits/stdc++.h>
#define r(i,n) for(int i=0;i<n;i++)
using namespace std;

struct PrimalDual{
  const int INF = 1<<28;
  typedef pair<int,int> P;
  struct edge{
    int to,cap,cost,rev;
    edge(){}
    edge(int to,int cap,int cost,int rev):to(to),cap(cap),cost(cost),rev(rev){}
  };

  int n;
  vector<vector<edge> > G;
  vector<int> h,dist,prevv,preve;

  PrimalDual(){}
  PrimalDual(int sz):n(sz),G(sz),h(sz),dist(sz),prevv(sz),preve(sz){}
  
  void add_edge(int from,int to,int cap,int cost){
    G[from].push_back(edge(to,cap,cost,G[to].size()));
    G[to].push_back(edge(from,0,-cost,G[from].size()-1));
  }

  int flow(int s,int t,int f){
    int res=0;
    fill(h.begin(),h.end(),0);
    while(f>0){
      priority_queue<P,vector<P>,greater<P> > que;
      fill(dist.begin(),dist.end(),INF);
      dist[s]=0;
      que.push(P(0,s));
      while(!que.empty()){
        P p=que.top();que.pop();
        int v=p.second;
        if(dist[v]<p.first) continue;
        for(int i=0;i<(int)G[v].size();i++){
          edge &e=G[v][i];
          if(e.cap>0&&dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]){
            dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];
            prevv[e.to]=v;
            preve[e.to]=i;
            que.push(P(dist[e.to],e.to));
          }
        }
      }
      if(dist[t]==INF) return -1;
      for(int v=0;v<n;v++) h[v]+=dist[v];
      int d=f;
      for(int v=t;v!=s;v=prevv[v]){
        d=min(d,G[prevv[v]][preve[v]].cap);
      }
      f-=d;
      res+=d*h[t];
      for(int v=t;v!=s;v=prevv[v]){
        edge &e=G[prevv[v]][preve[v]];
        e.cap-=d;
        G[v][e.rev].cap+=d;
      }
    }
    return res;
  }
};

int main(){
  int n,m,K;
  cin>>n>>m>>K;
  int a[n],b[m][n],t[m];
  r(i,n)cin>>a[i];
  r(i,m)r(j,n)cin>>b[i][j];
  r(i,m)cin>>t[i];
  int v=n+m+4;
  PrimalDual p(v);
  int start=n+m+1;
  int goal=n+m+2;
  int tite=n+m+3;
  r(i,n)p.add_edge(start,i,1,0);
  r(i,m+1){
    if(!i)p.add_edge(n+i,goal,1000,0);
    else p.add_edge(n+i,tite,t[i-1],0);
  }
  p.add_edge(tite,goal,n-K,0);
  r(i,n){
    r(j,m+1){
      if(!j)p.add_edge(i,n+j,1,-a[i]);
      else p.add_edge(i,n+j,1,-b[j-1][i]);
    }
  }
  cout<<-p.flow(start,goal,n)<<endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3436
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define DUMP(x) cerr << #x << "=" << x << endl
#define DUMP2(x, y) cerr<<"("<<#x<<", "<<#y<<") = ("<<x<<", "<<y<<")"<< endl
#define BINARY(x) static_cast<bitset<16> >(x)

#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define REP(i,m,n) for (int i=m;i<(int)(n);i++)

#define in_range(x, y, w, h) (0<=(int)(x) && (int)(x)<(int)(w) && 0<=(int)(y) && (int)(y)<(int)(h))
#define ALL(a) (a).begin(),(a).end()

typedef long long ll;
const int INF   = 1e9;
const ll  INFLL = 1e18;
typedef pair<int, int> PII;
int dx[4]={0, -1, 1, 0}, dy[4]={-1, 0, 0, 1};

const int MAX_V = 2000;

class MinCostFlow {
    struct edge { int to, cap, rev, cost;};
    vector<edge> G[MAX_V];

    int V;
    
    int dist[MAX_V];
    int prevv[MAX_V], preve[MAX_V];
    
public:
    MinCostFlow() {V=MAX_V;}
    MinCostFlow(int v) {
        V = v;
    }
    
    void add_edge(int from, int to, int cap, int cost) {
        G[from].push_back((edge){to, cap, (int)G[to].size(), cost});
        G[to].push_back((edge){from, 0, (int)G[from].size()-1, -cost});
    }
    
    // ????°??????¨???
    int min_cost_flow(int s, int t, int f) {
        int res=0;
        while (f>0) {
            fill(dist, dist+V, INF);
            dist[s]=0;
            bool update=true;
            while (update) {
                update = false;
                for (int v=0; v<V; v++) {
                    if (dist[v]==INF) continue;
                    for (int i=0; i<G[v].size(); i++) {
                        edge &e = G[v][i];
                        if (e.cap>0 && dist[e.to] > dist[v] + e.cost) {
                            dist[e.to] = dist[v] + e.cost;
                            prevv[e.to] = v;
                            preve[e.to] = i;
                            update = true;
                        }
                    }
                }
            }
            
            if (dist[t] == INF) {
                return -1;
            }
            
            int d=f;
            for (int v=t; v!=s; v=prevv[v]) {
                d = min(d, G[prevv[v]][preve[v]].cap);
            }
            f -= d;
            res += d*dist[t];
            for (int v=t; v!=s; v=prevv[v]) {
                edge &e = G[prevv[v]][preve[v]];
                e.cap -= d;
                G[v][e.rev].cap += d;
            }
        }
        return res;
    }
};

int main()
{
    ios::sync_with_stdio(false);

    int N, M, K;
    cin >> N >> M >> K;

    M++;

    vector<vector<int>> A(M, vector<int>(N));
    vector<int> T(M-1);

    rep(i, M) {
        rep(j, N) {
            cin >> A[i][j];
        }
    }

    rep(i, M-1) cin >> T[i];
 
    // Node 0            : ?????????
    // Node 1 - N        : ??¬?????????
    // Node N+1 - N+M    : ??????+??????
    // Node N+M+1        : ?§?????????°?????¶???
    // Node N+M+2        : ?????????

    const int SOURCE = 0;
    const int SINK   = N+M+2;
    const int X      = N+M+1;

    MinCostFlow flow(N+M+10);

    rep(i, N) {
        flow.add_edge(SOURCE, 1+i, 1, 0);
    }

    rep(i, N) {
        rep(j, M) {
            flow.add_edge(1+i, N+1+j, 1, 100 - A[j][i]);
        }
    }

    flow.add_edge(N+1, SINK, INF, 0);

    if (M > 1) {
        rep(i, M-1) {
            flow.add_edge(N+2+i, X, T[i], 0);
        }

        flow.add_edge(X, SINK, N-K, 0);
    }

    cout << N*100 - flow.min_cost_flow(0, SINK, N) << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3548
final_rank: 5

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

constexpr int MAX_V = 1000;
constexpr int INF = (1 << 29);

struct edge {
    int to, cap, cost, rev;
    edge(int to, int cap, int cost, int rev) :
        to{to}, cap{cap}, cost{cost}, rev{rev} {}
};

int V;
vector<edge> G[MAX_V];
int dist[MAX_V], prevv[MAX_V], preve[MAX_V];

void add_edge(int from, int to, int cap, int cost)
{
    G[from].emplace_back(to, cap, cost, G[to].size());
    G[to].emplace_back(from, 0, -cost, G[from].size() - 1);
}

int min_cost_flow(int s, int t, int f)
{
    int res = 0;
    while (f > 0) {
        fill(dist, dist + V, INF);
        dist[s] = 0;
        bool update = true;
        while (update) {
            update = false;
            for (int v = 0; v < V; v++) {
                if (dist[v] == INF) continue;
                for (int i = 0; i < (int)G[v].size(); i++) {
                    edge& e = G[v][i];
                    if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
                        dist[e.to] = dist[v] + e.cost;
                        prevv[e.to] = v;
                        preve[e.to] = i;
                        update = true;
                    }
                }
            }
        }
        if (dist[t] == INF) return -1;
        int d = f;
        for (int v = t; v != s; v = prevv[v]) {
            d = min(d, G[prevv[v]][preve[v]].cap);
        }
        f -= d;
        res += d * dist[t];
        for (int v = t; v != s; v = prevv[v]) {
            edge& e = G[prevv[v]][preve[v]];
            e.cap -= d;
            G[v][e.rev].cap += d;
        }
    }
    return res;
}

int main()
{
    int N, M, K;
    cin >> N >> M >> K;
    
    int S = N + (M + 1) + 1, T = S + 1;
    V = T + 1;
    for (int i = 0; i < N; i++) {
        int a;
        cin >> a;
        
        add_edge(S, i, 1, 0);
        add_edge(i, N, 1, -a);
    }
    

    for (int i = 0; i < M; i++) {
        for (int j = 0; j < N; j++) {
            int b;
            cin >> b;
            add_edge(j, N + i + 1, 1, -b);
        }
    }    
    
    for (int i = 0; i < M; i++) {
        int Ti;
        cin >> Ti;
        add_edge(N + i + 1, N + (M + 1), Ti, 0);
    }

    add_edge(N, T, INF, 0);
    add_edge(N + (M + 1), T, N - K, 0);

    cout << -min_cost_flow(S, T, N) << endl;    
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3396
final_rank: 2

code_snippet: #include "bits/stdc++.h"
using namespace std;



#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(auto i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()



typedef int Weight;
typedef int Cap;
const Weight W_INF = INT_MAX;
const Weight W_ZERO = 0;
const Cap C_INF = INT_MAX;
const Cap C_ZERO = 0;

struct Edge {
	int src, dst;
	Cap capacity;
	Weight cost;
	Edge(int src, int dst, const Cap& acap, const Weight& acost) :
		src(src), dst(dst), capacity(acap), cost(acost) {
	}
};
bool operator < (const Edge &e, const Edge &f) {
	return e.cost > f.cost;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;


#define RESIDUE(s,t) (capacity[s][t]-flow[s][t])
#define RCOST(u,v) (cost[u][v] + h[u] - h[v])

//??°?????????????????§???????????????????????¨?????????

//Graph &ag
//????????§???????????????(u, v, capacity, cost) ??????????????????(u, v, 0, -cost) ???????????°????????????????????¶?????????????????§????´???°????????§???????????°???????????????
//int s, int t
//?????????????§??????¨?????????
//?????????
//?????¨??¨????????????????????????
pair<Weight, Cap> minimumCostFlow(const Graph &ag, int s, int t) {
	//check???????´???°??????????????£???????????????
	Graph g(ag);
	for (int i = 0; i < ag.size(); ++i) {
		for (int j = 0; j < ag[i].size(); ++j) {
			int d = ag[i][j].dst;
			int s = ag[i][j].src;

			bool ok = false;
			for (int k = 0; k < ag[d].size(); ++k) {
				if (ag[d][k].src == s) {
					ok = true;
					break;
				}
			}
			if (!ok) {
				g[d].push_back(Edge(d, s, C_ZERO, -ag[i][j].cost));
			}
		}
	}
	const int n = g.size();
	vector<vector<Cap>> capacity(n, vector<Cap>(n)), flow(n, vector<Cap>(n));
	vector<vector<Weight>>cost(n, vector<Weight>(n));
	for (int u = 0; u < n; ++u) {
		for (auto e : g[u]) {
			capacity[e.src][e.dst] = capacity[e.src][e.dst] + e.capacity;
			cost[e.src][e.dst] = cost[e.src][e.dst] + e.cost;
		}
	}
	pair<Weight, Cap> total; // (cost, flow)
	vector<Weight> h(n);

	for (Cap F = C_INF; F > 0; ) { // residual flow
		vector<Weight> d(n, W_INF); d[s] = W_ZERO;
		vector<int> p(n, -1);
		priority_queue<Edge> Q; // "e < f" <=> "e.cost > f.cost"
		for (Q.push(Edge(-2, s, C_ZERO, W_ZERO)); !Q.empty(); ) {
			Edge e = Q.top(); Q.pop();
			if (p[e.dst] != -1) continue;
			p[e.dst] = e.src;
			FOR(f, g[e.dst]) {
				if (RESIDUE(f->src, f->dst) > 0) {
					if (d[f->dst] > d[f->src] + RCOST(f->src, f->dst)) {
						d[f->dst] = d[f->src] + RCOST(f->src, f->dst);
						Q.push(Edge(f->src, f->dst, 0, d[f->dst]));
					}
				}
			}
		}
		if (p[t] == -1) {
			break;
		}

		Cap f = F;
		for (int u = t; u != s; u = p[u]) {
			f = min(f, RESIDUE(p[u], u));
		}
		for (int u = t; u != s; u = p[u]) {
			total.first = total.first + f * cost[p[u]][u];
			flow[p[u]][u] = flow[p[u]][u] + f; flow[u][p[u]] = flow[u][p[u]] - f;
		}
		F = F - f;
		total.second = total.second + f;
		for (int u = 0; u < n; ++u) {
			h[u] = h[u] + d[u];
		}
	}
	return total;
}
void add_edge(Graph&g, const int from, const int to, const Cap& cap, const Weight& weight) {
	g[from].push_back(Edge(from, to, cap, weight));
}

int main() {
	int N, M, K; cin >> N >> M >> K;
	vector<int>myscores(N);
	vector<vector<int>>friscores(M, vector<int>(N));
	vector<int>cancheat(M);
	for (int i = 0; i < N; ++i) {
		cin >> myscores[i];
	}
	for (int i = 0; i < M; ++i) {
		for (int j = 0; j < N; ++j) {
			cin >> friscores[i][j];
		}
	}
	for (int i = 0; i < M; ++i) {
		cin >> cancheat[i];
	}

	const int start = 0;
	const int report = start + 1;
	const int my = report + N;
	const int fr_in = my + 1;
	const int fr_assemble = fr_in + M;
	const int goal = fr_assemble + 1;
	Graph g(goal+1);
	for (int i = 0; i < N; ++i) {
		add_edge(g, start, report + i, 1, 0);
	}
	for (int i = 0; i < N; ++i) {
		for (int j = 0; j < M; ++j) {
			add_edge(g, report + i, fr_in + j, 1, 100-friscores[j][i]);
		}
		add_edge(g, report + i, my, 1, 100-myscores[i]);
	}
	for (int j = 0; j < M; ++j) {
		add_edge(g, fr_in + j, fr_assemble, cancheat[j], 0);
	}
	add_edge(g, fr_assemble,goal, N - K, 0);
	add_edge(g, my, goal, N, 0);
	auto ans = minimumCostFlow(g, start, goal);
	cout << 100*N-ans.first<< endl;
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4152
final_rank: 6