Problem:
E: Arai's - Arai's -
問題
スクールアイドル時代から、国民的人気を誇ってきた女性アイドルグループArai's。今では、たくさんの「あらい」さんが所属する大規模なグループとして、世界レベルで活躍している。そして今日、新たなるプロジェクトの始動が決定した。彼女たちは、小さなユニットをいくつか結成することで、さらなる売上の向上を試みることになったのである。
Arai'sには「荒井」さんが
A
人，「新井」さんが
B
人在籍しており、合計で
A+B
人の「あらい」さんからなる。新ユニットは、「荒井」さん一人と「新井」さん一人のペアで構成する。（ここで、同じ「あらい」さんが複数のユニットに所属していはいけない。）ただし、ある「荒井」さんが一部の「新井」さんのことを良く思っていないうえに、同様にある「新井」さんが一部の「荒井」さんのことを良く思っていない。「あらい」さんたちはユニットを組む際に、良く思っていない「あらい」さんをペアとして認めてくれず、一方でも認めてくれなければユニットを組むことはできない。
Arai'sのマネージャーであるあなたは、なるべくたくさんのユニットを作りたいと考えているが、メンバーの交友関係からその限界を感じていた。そこであなたは、「あらい」さんたちと個別に面談し、ユニットを組ませたい「あらい」さんについての、良い噂を聞かせることを考えた。面談をした「あらい」さんは、噂に聞いた「あらい」さんを見直し、ユニットのペアとして認めるようになる。
しかし、あなたはそれほど時間をとることができないため、最大
K
回までしか噂を聞かせることができない。あなたは限られた時間の中で、結成できるユニットの数を最大化しようと試みた。あなたが結成できるユニットの数の最大値を求めよ。
入力形式
A
B
K
a_1
...
a_A
b_1
...
b_B
1行目には、「荒井」さんの人数
A
と「新井」さんの人数
B
(
1 \≤ A, B \≤ 200
であり
A
,
B
は整数)、噂を聞かせることができる人数
K
(
0 \≤ K \≤ 200
であり
K
は整数)が空白区切りで与えられる。
続く
A
行には、それぞれ長さ
B
の
0
と
1
のみからなる文字列が与えられる。そのうち
i
行目の文字列
a_i
の
j
文字目が
1
であるとき、
i
番目の「荒井」さんは
j
番目の「新井」さんを良く思っていない。
続く
B
行には、それぞれ長さ
A
の
0
と
1
のみからなる文字列が与えられる。そのうち
i
行目の文字列
b_i
の
j
文字目が
1
であるとき、
i
番目の「新井」さんは
j
番目の「荒井」さんを良く思っていない。
出力形式
あなたが結成できるユニット数の最大値を1行に出力せよ。
入力例1
3 3 4
111
111
111
111
111
111
出力例1
2
入力例2
3 3 2
101
100
010
001
011
111
出力例2
3
入力例3
5 6 3
101101
110110
010111
110110
110111
01010
10101
11101
01011
11011
11011
出力例3
4

Submitted solutions:

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

using LL = long long; using ll = LL;
using PII = pair<int, int>; using pii = PII;
using PLL = pair<LL, LL>; using pll = PLL;
using VI = vector<int>; using VL = vector<LL>;
const ll LINF = 1e18;
const int INF = 1e9;
#define FOR(i,s,t) for(int i =s; i < t;i++)
#define SZ(a) (int)a.size()
#define ALL(a) a.begin(),a.end()

struct Primal_Dual {
	struct edge {
		int to, rev;
		ll cap, cost;
		edge() {}
		edge(int to, ll cap, ll cost, int rev) :to(to), cap(cap), cost(cost), rev(rev) {}
	};
	vector<vector<edge>> graph;
	vector<int> prevv, preve;
	vector<ll> potential, min_cost;
	Primal_Dual(int V) :graph(V) {}

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

	ll min_cost_flow(int s, int t, int f) {
		int V = graph.size();
		ll ret = 0;
		priority_queue<pll, vector<pll>, greater<pll>> que;
		potential.assign(V, 0);
		preve.assign(V, -1);
		prevv.assign(V, -1);

		while (f > 0) {
			min_cost.assign(V, LINF);
			que.push({ 0,s });
			min_cost[s] = 0;

			while (que.size()) {
				pll p = que.top();
				que.pop();
				if (min_cost[p.second] < p.first) continue;
				for (int i = 0; i < graph[p.second].size(); i++) {
					edge& e = graph[p.second][i];
					ll nextCost = min_cost[p.second] + e.cost + potential[p.second] - potential[e.to];
					if (e.cap > 0 && min_cost[e.to] > nextCost) {
						min_cost[e.to] = nextCost;
						prevv[e.to] = p.second; preve[e.to] = i;
						que.push(pll(min_cost[e.to], e.to));
					}
				}
			}
			if (min_cost[t] == LINF) return -1;
			for (int v = 0; v < V; v++) potential[v] += min_cost[v];
			ll add = f;
			for (int v = t; v != s; v = prevv[v]) {
				add = min(add, graph[prevv[v]][preve[v]].cap);
			}
			f -= add;
			ret += add * potential[t];
			for (int v = t; v != s; v = prevv[v]) {
				edge& e = graph[prevv[v]][preve[v]];
				e.cap -= add;
				graph[v][e.rev].cap += add;
			}
		}
		return ret;
	}
};

void solve() {
	ll A, B, K; cin >> A >> B >> K;
	vector<string> a(A), b(B);
	for (auto& in : a) cin >> in;
	for (auto& in : b) cin >> in;

	ll S = A + B, T = A + B + 1;
	Primal_Dual clojure(A + B + 2);
	for (int i = 0; i < A; i++) clojure.add_edge(S, i, 1, 0);
	for (int i = 0; i < B; i++) clojure.add_edge(A+i, T, 1, 0);

	for (int i = 0; i < A; i++) {
		for (int j = 0; j < B; j++) {
			ll cost = 0;
			if (a[i][j] == '1') cost++;
			if (b[j][i] == '1') cost++;
			
			clojure.add_edge(i, A + j, 1, cost);
		}
	}

	ll ans = 0;
	while (true) {
		ll ret = clojure.min_cost_flow(S, T, 1);
//		cout << ret << endl;
		if (ret == -1) break;
		if (ret > K) break;
		K -= ret;
		ans++;
	}
	cout << ans << endl;
}

int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);

	solve();

	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 5720
final_rank: 11

code_snippet: #include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
using std::cout;
using std::cin;
using std::endl;
using ll=long long;
using ld=long double;
ll ILL=2167167167167167167;
const int INF=2100000000;
const ll mod=998244353;
#define rep(i,a) for (ll i=0;i<a;i++)
#define all(p) p.begin(),p.end()
template<class T> using _pq = priority_queue<T, vector<T>, greater<T>>;
template<class T> ll LB(vector<T> &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> ll UB(vector<T> &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> bool chmin(T &a,const T &b){if(a>b){a=b;return 1;}else return 0;}
template<class T> bool chmax(T &a,const T &b){if(a<b){a=b;return 1;}else return 0;}
template<class T> void So(vector<T> &v) {sort(v.begin(),v.end());}
template<class T> void Sore(vector<T> &v) {sort(v.begin(),v.end(),[](T x,T y){return x>y;});}
void yneos(bool a){if(a) cout<<"Yes\n"; else cout<<"No\n";}
template<class T> void vec_out(vector<T> &p){for(int i=0;i<(int)(p.size());i++){if(i) cout<<" ";cout<<p[i];}cout<<"\n";}
template<class T> T min(vector<T> &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmin(ans,x);return ans;}
template<class T> T max(vector<T> &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmax(ans,x);return ans;}

namespace atcoder {
namespace internal {

template <class E> struct csr {
    std::vector<int> start;
    std::vector<E> elist;
    explicit csr(int n, const std::vector<std::pair<int, E>>& edges)
        : start(n + 1), elist(edges.size()) {
        for (auto e : edges) {
            start[e.first + 1]++;
        }
        for (int i = 1; i <= n; i++) {
            start[i] += start[i - 1];
        }
        auto counter = start;
        for (auto e : edges) {
            elist[counter[e.first]++] = e.second;
        }
    }
};

}  // namespace internal

namespace internal {

template <class T> struct simple_queue {
    std::vector<T> payload;
    int pos = 0;
    void reserve(int n) { payload.reserve(n); }
    int size() const { return int(payload.size()) - pos; }
    bool empty() const { return pos == int(payload.size()); }
    void push(const T& t) { payload.push_back(t); }
    T& front() { return payload[pos]; }
    void clear() {
        payload.clear();
        pos = 0;
    }
    void pop() { pos++; }
};

}  // namespace internal



template <class Cap, class Cost> struct mcf_graph {
  public:
    mcf_graph() {}
    explicit mcf_graph(int n) : _n(n) {}

    int add_edge(int from, int to, Cap cap, Cost cost) {
        assert(0 <= from && from < _n);
        assert(0 <= to && to < _n);
        assert(0 <= cap);
        assert(0 <= cost);
        int m = int(_edges.size());
        _edges.push_back({from, to, cap, 0, cost});
        return m;
    }

    struct edge {
        int from, to;
        Cap cap, flow;
        Cost cost;
    };

    edge get_edge(int i) {
        int m = int(_edges.size());
        assert(0 <= i && i < m);
        return _edges[i];
    }
    std::vector<edge> edges() { return _edges; }

    std::pair<Cap, Cost> flow(int s, int t) {
        return flow(s, t, std::numeric_limits<Cap>::max());
    }
    std::pair<Cap, Cost> flow(int s, int t, Cap flow_limit) {
        return slope(s, t, flow_limit).back();
    }
    std::vector<std::pair<Cap, Cost>> slope(int s, int t) {
        return slope(s, t, std::numeric_limits<Cap>::max());
    }
    std::vector<std::pair<Cap, Cost>> slope(int s, int t, Cap flow_limit) {
        assert(0 <= s && s < _n);
        assert(0 <= t && t < _n);
        assert(s != t);

        int m = int(_edges.size());
        std::vector<int> edge_idx(m);

        auto g = [&]() {
            std::vector<int> degree(_n), redge_idx(m);
            std::vector<std::pair<int, _edge>> elist;
            elist.reserve(2 * m);
            for (int i = 0; i < m; i++) {
                auto e = _edges[i];
                edge_idx[i] = degree[e.from]++;
                redge_idx[i] = degree[e.to]++;
                elist.push_back({e.from, {e.to, -1, e.cap - e.flow, e.cost}});
                elist.push_back({e.to, {e.from, -1, e.flow, -e.cost}});
            }
            auto _g = internal::csr<_edge>(_n, elist);
            for (int i = 0; i < m; i++) {
                auto e = _edges[i];
                edge_idx[i] += _g.start[e.from];
                redge_idx[i] += _g.start[e.to];
                _g.elist[edge_idx[i]].rev = redge_idx[i];
                _g.elist[redge_idx[i]].rev = edge_idx[i];
            }
            return _g;
        }();

        auto result = slope(g, s, t, flow_limit);

        for (int i = 0; i < m; i++) {
            auto e = g.elist[edge_idx[i]];
            _edges[i].flow = _edges[i].cap - e.cap;
        }

        return result;
    }
	std::vector<Cost> slope_all(int s, int t,Cap flow_limit) {
        std::vector<std::pair<Cap, Cost>> tmp=slope(s, t, flow_limit);
		std::vector<Cost> ans((*tmp.rbegin()).first+1);
		ans[0]=0;
		for(int i=0;i<(int)(tmp.size())-1;i++){
			Cost diff=(tmp[i+1].second-tmp[i].second)/(tmp[i+1].first-tmp[i].first);
			for(int j=1+tmp[i].first;j<=tmp[i+1].first;j++){
				ans[j]=ans[j-1]+diff;
			}
		}
		return ans;
    }
	std::vector<Cost> slope_all(int s, int t){
		return slope_all(s,t,std::numeric_limits<Cap>::max());
    }

  private:
    int _n;
    std::vector<edge> _edges;

    // inside edge
    struct _edge {
        int to, rev;
        Cap cap;
        Cost cost;
    };

    std::vector<std::pair<Cap, Cost>> slope(internal::csr<_edge>& g,
                                            int s,
                                            int t,
                                            Cap flow_limit) {
        // variants (C = maxcost):
        // -(n-1)C <= dual[s] <= dual[i] <= dual[t] = 0
        // reduced cost (= e.cost + dual[e.from] - dual[e.to]) >= 0 for all edge

        // dual_dist[i] = (dual[i], dist[i])
        std::vector<std::pair<Cost, Cost>> dual_dist(_n);
        std::vector<int> prev_e(_n);
        std::vector<bool> vis(_n);
        struct Q {
            Cost key;
            int to;
            bool operator<(Q r) const { return key > r.key; }
        };
        std::vector<int> que_min;
        std::vector<Q> que;
        auto dual_ref = [&]() {
            for (int i = 0; i < _n; i++) {
                dual_dist[i].second = std::numeric_limits<Cost>::max();
            }
            std::fill(vis.begin(), vis.end(), false);
            que_min.clear();
            que.clear();

            // que[0..heap_r) was heapified
            size_t heap_r = 0;

            dual_dist[s].second = 0;
            que_min.push_back(s);
            while (!que_min.empty() || !que.empty()) {
                int v;
                if (!que_min.empty()) {
                    v = que_min.back();
                    que_min.pop_back();
                } else {
                    while (heap_r < que.size()) {
                        heap_r++;
                        std::push_heap(que.begin(), que.begin() + heap_r);
                    }
                    v = que.front().to;
                    std::pop_heap(que.begin(), que.end());
                    que.pop_back();
                    heap_r--;
                }
                if (vis[v]) continue;
                vis[v] = true;
                if (v == t) break;
                // dist[v] = shortest(s, v) + dual[s] - dual[v]
                // dist[v] >= 0 (all reduced cost are positive)
                // dist[v] <= (n-1)C
                Cost dual_v = dual_dist[v].first, dist_v = dual_dist[v].second;
                for (int i = g.start[v]; i < g.start[v + 1]; i++) {
                    auto e = g.elist[i];
                    if (!e.cap) continue;
                    // |-dual[e.to] + dual[v]| <= (n-1)C
                    // cost <= C - -(n-1)C + 0 = nC
                    Cost cost = e.cost - dual_dist[e.to].first + dual_v;
                    if (dual_dist[e.to].second - dist_v > cost) {
                        Cost dist_to = dist_v + cost;
                        dual_dist[e.to].second = dist_to;
                        prev_e[e.to] = e.rev;
                        if (dist_to == dist_v) {
                            que_min.push_back(e.to);
                        } else {
                            que.push_back(Q{dist_to, e.to});
                        }
                    }
                }
            }
            if (!vis[t]) {
                return false;
            }

            for (int v = 0; v < _n; v++) {
                if (!vis[v]) continue;
                // dual[v] = dual[v] - dist[t] + dist[v]
                //         = dual[v] - (shortest(s, t) + dual[s] - dual[t]) +
                //         (shortest(s, v) + dual[s] - dual[v]) = - shortest(s,
                //         t) + dual[t] + shortest(s, v) = shortest(s, v) -
                //         shortest(s, t) >= 0 - (n-1)C
                dual_dist[v].first -= dual_dist[t].second - dual_dist[v].second;
            }
            return true;
        };
        Cap flow = 0;
        Cost cost = 0, prev_cost_per_flow = -1;
        std::vector<std::pair<Cap, Cost>> result = {{Cap(0), Cost(0)}};
        while (flow < flow_limit) {
            if (!dual_ref()) break;
            Cap c = flow_limit - flow;
            for (int v = t; v != s; v = g.elist[prev_e[v]].to) {
                c = std::min(c, g.elist[g.elist[prev_e[v]].rev].cap);
            }
            for (int v = t; v != s; v = g.elist[prev_e[v]].to) {
                auto& e = g.elist[prev_e[v]];
                e.cap += c;
                g.elist[e.rev].cap -= c;
            }
            Cost d = -dual_dist[s].first;
            flow += c;
            cost += c * d;
            if (prev_cost_per_flow == d) {
                result.pop_back();
            }
            result.push_back({flow, cost});
            prev_cost_per_flow = d;
        }
        return result;
    }
};


}  // namespace atcoder
using namespace atcoder;



void solve();
// oddloop
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int t=1;
	//cin>>t;
	rep(i,t) solve();
}

void solve(){
	int A,B,K;
	cin>>A>>B>>K;
	mcf_graph<int,int> G(A+B+2);
	int S=A+B,T=S+1;
	rep(i,A) G.add_edge(S,i,1,0);
	rep(i,B) G.add_edge(i+A,T,1,0);
	vector<vector<int>> p(A,vector<int>(B));
	rep(i,A) rep(j,B){
		char c;
		cin>>c;
		p[i][j]+=(int)(c-'0');
	}
	rep(j,B) rep(i,A){
		char c;
		cin>>c;
		p[i][j]+=(int)(c-'0');
	}
	rep(i,A) rep(j,B) G.add_edge(i,j+A,1,p[i][j]);
	auto ans=G.slope_all(S,T);
	ans.push_back(INF);
	int a=UB(ans,K);
	cout<<a-1<<"\n";
}
accuracy: 1
time_ms: 10
memory_kb: 7344
final_rank: 14

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}

struct Primal_Dual{
    const int INF=(1<<30);
    struct edge{
        int to,cap,cost,rev;
    };
    vector<vector<edge>> G;
    vector<int> potential,min_cost,prevv,preve;
    Primal_Dual(int V):G(V){}
    void add_edge(int s,int t,int cap,int cost){
        G[s].push_back((edge){t,cap,cost,(int)(G[t].size())});
        G[t].push_back((edge){s,0,-cost,(int)(G[s].size()-1)});
    }
    int min_cost_flow(int s,int t,int f){
        int V=G.size(); int res=0;
        priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> pq;
        potential.assign(V,0);
        preve.assign(V,-1);
        prevv.assign(V,-1);
        while(f>0){
            min_cost.assign(V,INF);
            pq.push(make_pair(0,s));
            min_cost[s]=0;
            while(pq.size()){
                auto p=pq.top(); pq.pop();
                if(min_cost[p.second]<p.first)continue;
                int i=-1;
                for(auto &e:G[p.second]){
                    i++;
                    int nextcost=min_cost[p.second]+e.cost+potential[p.second]-potential[e.to];
                    if(e.cap>0 and min_cost[e.to]>nextcost){
                        min_cost[e.to]=nextcost;
                        prevv[e.to]=p.second;
                        preve[e.to]=i;
                        pq.push(make_pair(min_cost[e.to],e.to));
                    }
                }
            }
            if(min_cost[t]==INF)return -1; // 流せない
            for(int v=0;v<V;v++){
                potential[v]+=min_cost[v];
            }
            int Addflow=f;
            for(int v=t;v!=s;v=prevv[v]){
                Addflow=min(Addflow,G[prevv[v]][preve[v]].cap);
            }
            f-=Addflow;
            res+=Addflow*potential[t];
            for(int v=t;v!=s;v=prevv[v]){
                edge &e=G[prevv[v]][preve[v]];
                e.cap-=Addflow;
                G[v][e.rev].cap+=Addflow;
            }
        }
        return res;
    }
};

char a[211][211],b[211][211];

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int A,B,K; cin >> A >> B >> K;
    Primal_Dual G(A+B+2);
    int S=A+B,T=A+B+1;
    for(int i=0;i<A;i++){
        G.add_edge(S,i,1,0);
    }
    for(int i=0;i<B;i++){
        G.add_edge(A+i,T,1,0);
    }
    for(int i=0;i<A;i++){
        for(int j=0;j<B;j++){
            cin >> a[i][j];
        }
    }
    for(int i=0;i<B;i++){
        for(int j=0;j<A;j++){
            cin >> b[i][j];
        }
    }
    for(int i=0;i<A;i++){
        for(int j=0;j<B;j++){
            G.add_edge(i,A+j,1,(a[i][j]-'0')+(b[j][i]-'0'));
        }
    }
    int res=0;
    int sum=0;
    for(int i=1;i<=min(A,B);i++){
        int flow=G.min_cost_flow(S,T,1);
        if(flow==-1)break;
        sum+=flow;
        if(sum<=K )res=i;
        else break;
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 20
memory_kb: 4960
final_rank: 5

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

template <class T>
struct Primal_Dual {
  using Pa = pair<T, int>;
  int infinity = (int)(1e9);
  struct edge {
    int to;
    T cap, cost;
    int rev;
  };
  int v;
  vector<vector<edge>> edges;
  vector<T> h;
  vector<T> dist;
  vector<int> prevv, preve;
  Primal_Dual(int vsize = 1) {
    v = vsize;
    edges.resize(v);
    h.resize(v);
    dist.resize(v);
    prevv.resize(v);
    preve.resize(v);
  }
  bool add(int from, int to, T cap, T cost) {
    edges[from].push_back((edge){to, cap, cost, (int)edges[to].size()});
    edges[to].push_back((edge){from, 0, -cost, (int)edges[from].size() - 1});
    return 1;
  }
  T solve(int s, int t, T f) {
    T ans = 0;
    h.assign(v, 0);
    while (f > 0) {
      priority_queue<Pa, vector<Pa>, greater<Pa>> qu;
      dist.assign(v, infinity);
      dist[s] = 0;
      qu.push({0, s});
      while (!qu.empty()) {
        Pa now = qu.top();
        qu.pop();
        int nowv = now.second;
        if (dist[nowv] < now.first) continue;
        for (int i = 0; i < (int)edges[nowv].size(); ++i) {
          edge &e = edges[nowv][i];
          if (e.cap > 0 &&
              dist[e.to] > dist[nowv] + e.cost + h[nowv] - h[e.to]) {
            dist[e.to] = dist[nowv] + e.cost + h[nowv] - h[e.to];
            prevv[e.to] = nowv;
            preve[e.to] = i;
            qu.push({dist[e.to], e.to});
          }
        }
      }
      if (dist[t] == infinity) return -1;
      for (int i = 0; i < v; ++i) h[i] += dist[i];
      T d = f;
      for (int i = t; i != s; i = prevv[i])
        d = min(d, edges[prevv[i]][preve[i]].cap);
      f -= d;
      ans += d * h[t];
      for (int i = t; i != s; i = prevv[i]) {
        edge &e = edges[prevv[i]][preve[i]];
        e.cap -= d;
        edges[i][e.rev].cap += d;
      }
    }
    return ans;
  }
};

int a, b, k;
vector<vector<int>> cnt;

int main() {
  cin >> a >> b >> k;
  cnt.assign(a, vector<int>(b, 0));
  for (int i = 0; i < a; ++i) {
    string s;
    cin >> s;
    for (int j = 0; j < b; ++j) cnt[i][j] += s[j] - '0';
  }
  for (int i = 0; i < b; ++i) {
    string s;
    cin >> s;
    for (int j = 0; j < a; ++j) cnt[j][i] += s[j] - '0';
  }
  Primal_Dual<int> pd(a + b + 2);
  for (int i = 0; i < a; ++i) pd.add(a + b, i, 1, 0);
  for (int i = 0; i < b; ++i) pd.add(i + a, a + b + 1, 1, 0);
  for (int i = 0; i < a; ++i)
    for (int j = 0; j < b; ++j) pd.add(i, j + a, 1, cnt[i][j]);
  int res = 0;
  while (res < min(a, b)) {
    k -= pd.solve(a + b, a + b + 1, 1);
    if (k < 0) break;
    ++res;
  }
  cout << res << endl;
  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 5324
final_rank: 8

code_snippet: #pragma GCC optimize("O3")
#include<bits/stdc++.h> 
using namespace std;
using ll=long long;
using P=pair<ll,ll>;
template<class T> using V=vector<T>; 
#define fi first
#define se second
#define all(v) (v).begin(),(v).end()
const ll inf=(1e18);
//const ll mod=998244353;
const ll mod=1000000007;
ll GCD(ll a,ll b) {return b ? GCD(b,a%b):a;}
ll LCM(ll c,ll d){return c/GCD(c,d)*d;}
struct __INIT{__INIT(){cin.tie(0);ios::sync_with_stdio(false);cout<<fixed<<setprecision(15);}} __init;
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T>void debag(const vector<T> &a){cerr<<"debag :";for(auto v:a)cerr<<v<<" ";cerr<<"\n";}
template<class T>void print(const vector<T> &a){for(auto v:a)cout<<v<<" ";cout<<"\n";}
struct PrimalDual{
    const ll INF=(1ll<<60);
    struct edge{
        int to,rev;ll cap,cost;bool isrev;
        edge(int to,ll cap,ll cost,int rev,bool isrev):to(to),cap(cap),cost(cost),rev(rev),isrev(isrev){}
    };
    vector<vector<edge>> graph;
    vector<ll> potential,min_cost;
    vector<int> prev_v,prev_e;

    PrimalDual(int V):graph(V){}

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

    ll min_cost_flow(int s,int t,ll f){
        int N=graph.size();
        ll res=0;
        priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<pair<ll,int>>> pq;
        potential.assign(N,0);
        prev_e.assign(N,-1);
        prev_v.assign(N,-1);

        while(f>0){
            min_cost.assign(N,INF);
            pq.emplace(0,s);
            min_cost[s]=0;
            while(pq.size()){
                ll cost=pq.top().fi,cur=pq.top().se;
                pq.pop();
                if(min_cost[cur]<cost)continue;
                for(int i=0;i<graph[cur].size();i++){
                    edge &e=graph[cur][i];
                    ll next_cost=min_cost[cur]+e.cost+potential[cur]-potential[e.to];
                    if(e.cap>0&&min_cost[e.to]>next_cost){
                        min_cost[e.to]=next_cost;
                        prev_v[e.to]=cur;
                        prev_e[e.to]=i;
                        pq.emplace(min_cost[e.to],e.to);
                    }
                }
            }
            if(min_cost[t]>=INF)return -1;
            for(int v=0;v<N;v++)potential[v]+=min_cost[v];
            ll add_flow=f;
            for(int v=t;v!=s;v=prev_v[v]){
                chmin(add_flow,graph[prev_v[v]][prev_e[v]].cap);
            }
            f-=add_flow;
            res+=add_flow*potential[t];
            for(int v=t;v!=s;v=prev_v[v]){
                edge &e=graph[prev_v[v]][prev_e[v]];
                e.cap-=add_flow;
                graph[v][e.rev].cap+=add_flow;
            }
        }
        return res;
    }
};
int main(){
    ll A,B,k;
    cin>>A>>B>>k;
    V<string> a(A),b(B);
    for(int i=0;i<A;i++)cin>>a[i];
    for(int i=0;i<B;i++)cin>>b[i];
    V<V<bool>> ngA(205,V<bool>(205,false)),ngB(205,V<bool>(205,false));;
    for(int i=0;i<A;i++){
          for(int j=0;j<B;j++){
                 if(a[i][j]=='1'){
                     ngA[i][j]=true;
                 }
          }
    }
    for(int i=0;i<B;i++){
         for(int j=0;j<A;j++){
                 if(b[i][j]=='1'){
                     ngB[i][j]=true;
                 }                
         }
    }
    ll l=0,r=min(A,B)+1;
    int ma=A+B+5;
    while(r-l>1){
           ll mid=(l+r)/2;
           
           PrimalDual f(ma);
           int S=A+B+1,T=A+B+2;
           for(int i=0;i<A;i++){
                  f.add_edge(S,i,1,0);
           }
           for(int i=0;i<B;i++){
                  f.add_edge(i+A,T,1,0);
           }
           for(int i=0;i<A;i++){
                for(int j=0;j<B;j++){
                    int cost=0;
                    if(ngA[i][j])cost++;
                    if(ngB[j][i])cost++;
                    f.add_edge(i,j+A,1,cost);
                }
           }
           ll v=f.min_cost_flow(S,T,mid);
          // cout<<v<<" "<<mid<<"\n";
           if(v==-1)v=inf;
           if(v>k)r=mid;
           else l=mid;
    }
    cout<<l<<"\n";
}
accuracy: 1
time_ms: 180
memory_kb: 6692
final_rank: 15

code_snippet: #include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
//#pragma GCC target("avx2")
#pragma GCC optimize("unroll-loops")
using namespace std;
//#include<boost/multiprecision/cpp_int.hpp>
//#include<boost/multiprecision/cpp_dec_float.hpp>
//namespace mp=boost::multiprecision;
//#define mulint mp::cpp_int
//#define mulfloat mp::cpp_dec_float_100
struct __INIT{__INIT(){cin.tie(0);ios::sync_with_stdio(false);cout<<fixed<<setprecision(15);}} __init;
#define INF (1<<30)
#define LINF (lint)(1LL<<56)
#define endl "\n"
#define rep(i,n) for(lint (i)=0;(i)<(n);(i)++)
#define reprev(i,n) for(lint (i)=(n-1);(i)>=0;(i)--)
#define flc(x) __builtin_popcountll(x)
#define pint pair<int,int>
#define pdouble pair<double,double>
#define plint pair<lint,lint>
#define fi first
#define se second
#define all(x) x.begin(),x.end()
#define vec vector<lint>
#define nep(x) next_permutation(all(x))
typedef long long lint;
int dx[8]={1,1,0,-1,-1,-1,0,1};
int dy[8]={0,1,1,1,0,-1,-1,-1};
const int MAX_N=3e5+5;
template<class T>bool chmax(T &a,const T &b){if(a<b){a=b;return 1;}return 0;}
template<class T>bool chmin(T &a,const T &b){if(b<a){a=b;return 1;}return 0;}
//vector<int> bucket[MAX_N/1000];
constexpr int MOD=1000000007;
//constexpr int MOD=998244353;
/*#include<atcoder/all>
using namespace atcoder;
typedef __int128_t llint;*/

namespace atcoder {
namespace internal {
template <class T> struct simple_queue {
    std::vector<T> payload;
    int pos = 0;
    void reserve(int n) { payload.reserve(n); }
    int size() const { return int(payload.size()) - pos; }
    bool empty() const { return pos == int(payload.size()); }
    void push(const T& t) { payload.push_back(t); }
    T& front() { return payload[pos]; }
    void clear() {
        payload.clear();
        pos = 0;
    }
    void pop() { pos++; }
};
}  // namespace internal
}

namespace atcoder {
template <class Cap> struct mf_graph {
  public:
    mf_graph() : _n(0) {}
    mf_graph(int n) : _n(n), g(n) {}
    int add_edge(int from, int to, Cap cap) {
        assert(0 <= from && from < _n);
        assert(0 <= to && to < _n);
        assert(0 <= cap);
        int m = int(pos.size());
        pos.push_back({from, int(g[from].size())});
        g[from].push_back(_edge{to, int(g[to].size()), cap});
        g[to].push_back(_edge{from, int(g[from].size()) - 1, 0});
        return m;
    }
    struct edge {
        int from, to;
        Cap cap, flow;
    };
    edge get_edge(int i) {
        int m = int(pos.size());
        assert(0 <= i && i < m);
        auto _e = g[pos[i].first][pos[i].second];
        auto _re = g[_e.to][_e.rev];
        return edge{pos[i].first, _e.to, _e.cap + _re.cap, _re.cap};
    }
    std::vector<edge> edges() {
        int m = int(pos.size());
        std::vector<edge> result;
        for (int i = 0; i < m; i++) {
            result.push_back(get_edge(i));
        }
        return result;
    }
    void change_edge(int i, Cap new_cap, Cap new_flow) {
        int m = int(pos.size());
        assert(0 <= i && i < m);
        assert(0 <= new_flow && new_flow <= new_cap);
        auto& _e = g[pos[i].first][pos[i].second];
        auto& _re = g[_e.to][_e.rev];
        _e.cap = new_cap - new_flow;
        _re.cap = new_flow;
    }
    Cap flow(int s, int t) {
        return flow(s, t, std::numeric_limits<Cap>::max());
    }
    Cap flow(int s, int t, Cap flow_limit) {
        assert(0 <= s && s < _n);
        assert(0 <= t && t < _n);
        std::vector<int> level(_n), iter(_n);
        internal::simple_queue<int> que;
        auto bfs = [&]() {
            std::fill(level.begin(), level.end(), -1);
            level[s] = 0;
            que.clear();
            que.push(s);
            while (!que.empty()) {
                int v = que.front();
                que.pop();
                for (auto e : g[v]) {
                    if (e.cap == 0 || level[e.to] >= 0) continue;
                    level[e.to] = level[v] + 1;
                    if (e.to == t) return;
                    que.push(e.to);
                }
            }
        };
        auto dfs = [&](auto self, int v, Cap up) {
            if (v == s) return up;
            Cap res = 0;
            int level_v = level[v];
            for (int& i = iter[v]; i < int(g[v].size()); i++) {
                _edge& e = g[v][i];
                if (level_v <= level[e.to] || g[e.to][e.rev].cap == 0) continue;
                Cap d =
                    self(self, e.to, std::min(up - res, g[e.to][e.rev].cap));
                if (d <= 0) continue;
                g[v][i].cap += d;
                g[e.to][e.rev].cap -= d;
                res += d;
                if (res == up) break;
            }
            return res;
        };
        Cap flow = 0;
        while (flow < flow_limit) {
            bfs();
            if (level[t] == -1) break;
            std::fill(iter.begin(), iter.end(), 0);
            while (flow < flow_limit) {
                Cap f = dfs(dfs, t, flow_limit - flow);
                if (!f) break;
                flow += f;
            }
        }
        return flow;
    }
    std::vector<bool> min_cut(int s) {
        std::vector<bool> visited(_n);
        internal::simple_queue<int> que;
        que.push(s);
        while (!que.empty()) {
            int p = que.front();
            que.pop();
            visited[p] = true;
            for (auto e : g[p]) {
                if (e.cap && !visited[e.to]) {
                    visited[e.to] = true;
                    que.push(e.to);
                }
            }
        }
        return visited;
    }
  private:
    int _n;
    struct _edge {
        int to, rev;
        Cap cap;
    };
    std::vector<std::pair<int, int>> pos;
    std::vector<std::vector<_edge>> g;
};
}

namespace atcoder {
template <class Cap, class Cost> struct mcf_graph {
  public:
    mcf_graph() {}
    mcf_graph(int n) : _n(n), g(n) {}
    int add_edge(int from, int to, Cap cap, Cost cost) {
        assert(0 <= from && from < _n);
        assert(0 <= to && to < _n);
        int m = int(pos.size());
        pos.push_back({from, int(g[from].size())});
        g[from].push_back(_edge{to, int(g[to].size()), cap, cost});
        g[to].push_back(_edge{from, int(g[from].size()) - 1, 0, -cost});
        return m;
    }
    struct edge {
        int from, to;
        Cap cap, flow;
        Cost cost;
    };
    edge get_edge(int i) {
        int m = int(pos.size());
        assert(0 <= i && i < m);
        auto _e = g[pos[i].first][pos[i].second];
        auto _re = g[_e.to][_e.rev];
        return edge{
            pos[i].first, _e.to, _e.cap + _re.cap, _re.cap, _e.cost,
        };
    }
    std::vector<edge> edges() {
        int m = int(pos.size());
        std::vector<edge> result(m);
        for (int i = 0; i < m; i++) {
            result[i] = get_edge(i);
        }
        return result;
    }
    std::pair<Cap, Cost> flow(int s, int t) {
        return flow(s, t, std::numeric_limits<Cap>::max());
    }
    std::pair<Cap, Cost> flow(int s, int t, Cap flow_limit) {
        return slope(s, t, flow_limit).back();
    }
    std::vector<std::pair<Cap, Cost>> slope(int s, int t) {
        return slope(s, t, std::numeric_limits<Cap>::max());
    }
    std::vector<std::pair<Cap, Cost>> slope(int s, int t, Cap flow_limit) {
        assert(0 <= s && s < _n);
        assert(0 <= t && t < _n);
        assert(s != t);
        // variants (C = maxcost):
        // -(n-1)C <= dual[s] <= dual[i] <= dual[t] = 0
        // reduced cost (= e.cost + dual[e.from] - dual[e.to]) >= 0 for all edge
        std::vector<Cost> dual(_n, 0), dist(_n);
        std::vector<int> pv(_n), pe(_n);
        std::vector<bool> vis(_n);
        auto dual_ref = [&]() {
            std::fill(dist.begin(), dist.end(),
                      std::numeric_limits<Cost>::max());
            std::fill(pv.begin(), pv.end(), -1);
            std::fill(pe.begin(), pe.end(), -1);
            std::fill(vis.begin(), vis.end(), false);
            struct Q {
                Cost key;
                int to;
                bool operator<(Q r) const { return key > r.key; }
            };
            std::priority_queue<Q> que;
            dist[s] = 0;
            que.push(Q{0, s});
            while (!que.empty()) {
                int v = que.top().to;
                que.pop();
                if (vis[v]) continue;
                vis[v] = true;
                if (v == t) break;
                // dist[v] = shortest(s, v) + dual[s] - dual[v]
                // dist[v] >= 0 (all reduced cost are positive)
                // dist[v] <= (n-1)C
                for (int i = 0; i < int(g[v].size()); i++) {
                    auto e = g[v][i];
                    if (vis[e.to] || !e.cap) continue;
                    // |-dual[e.to] + dual[v]| <= (n-1)C
                    // cost <= C - -(n-1)C + 0 = nC
                    Cost cost = e.cost - dual[e.to] + dual[v];
                    if (dist[e.to] - dist[v] > cost) {
                        dist[e.to] = dist[v] + cost;
                        pv[e.to] = v;
                        pe[e.to] = i;
                        que.push(Q{dist[e.to], e.to});
                    }
                }
            }
            if (!vis[t]) {
                return false;
            }
            for (int v = 0; v < _n; v++) {
                if (!vis[v]) continue;
                // dual[v] = dual[v] - dist[t] + dist[v]
                //         = dual[v] - (shortest(s, t) + dual[s] - dual[t]) + (shortest(s, v) + dual[s] - dual[v])
                //         = - shortest(s, t) + dual[t] + shortest(s, v)
                //         = shortest(s, v) - shortest(s, t) >= 0 - (n-1)C
                dual[v] -= dist[t] - dist[v];
            }
            return true;
        };
        Cap flow = 0;
        Cost cost = 0, prev_cost = -1;
        std::vector<std::pair<Cap, Cost>> result;
        result.push_back({flow, cost});
        while (flow < flow_limit) {
            if (!dual_ref()) break;
            Cap c = flow_limit - flow;
            for (int v = t; v != s; v = pv[v]) {
                c = std::min(c, g[pv[v]][pe[v]].cap);
            }
            for (int v = t; v != s; v = pv[v]) {
                auto& e = g[pv[v]][pe[v]];
                e.cap -= c;
                g[v][e.rev].cap += c;
            }
            Cost d = -dual[s];
            flow += c;
            cost += c * d;
            if (prev_cost == d) {
                result.pop_back();
            }
            result.push_back({flow, cost});
            prev_cost = cost;
        }
        return result;
    }
  private:
    int _n;
    struct _edge {
        int to, rev;
        Cap cap;
        Cost cost;
    };
    std::vector<std::pair<int, int>> pos;
    std::vector<std::vector<_edge>> g;
};
}

using namespace atcoder;

int main(void){
    int A,B,K;
    cin >> A >> B >> K;
    mf_graph<int> G(A+B+2);
    rep(i,A) G.add_edge(A+B,i,1);
    rep(i,B) G.add_edge(A+i,A+B+1,1);
    string a[A],b[B];
    rep(i,A) cin >> a[i];
    rep(i,B) cin >> b[i];
    lint needs[A][B];
    /*rep(i,A) rep(j,B){
        if(a[i][j]=='0' && b[j][i]=='0') G.add_edge(i,A+j,1);
        else G.add_edge(i,A+j,0);
    }*/
    /*int ans=G.flow(A+B,A+B+1);
    vector<mf_graph<int>::edge> es=G.edges();
    int needs[A][B];
    bool used[A+B]={};
    rep(i,es.size()){
        if(es[i].from==A+B || es[i].to==A+B+1) continue;
        if(es[i].flow==1){
            int from=es[i].from,to=es[i].to;
            used[from]=true;
            used[to]=true;
        }
    }*/
    rep(i,A) rep(j,B) needs[i][j]=INF;
    /*rep(i,es.size()){
        if(es[i].from==A+B || es[i].to==A+B+1) continue;
        if(es[i].flow==0){
            int from=es[i].from,to=es[i].to-A;
            int cost=2;
            if(a[from][to]=='0') cost--;
            if(b[to][from]=='0') cost--;
            needs[from][to]=cost;
            if(used[from] || used[to]) needs[from][to]=INF;
        }
    }*/
    rep(i,A) rep(j,B){
        int cost=2;
        if(a[i][j]=='0') cost--;
        if(b[j][i]=='0') cost--;
        needs[i][j]=cost;
    }
    mcf_graph<lint,lint> G2(A+B+2);
    rep(i,A){
        G2.add_edge(A+B,i,1,0);
    }
    rep(i,B){
        G2.add_edge(A+i,A+B+1,1,0);
    }
    rep(i,A) rep(j,B){
        int from=i,to=A+j;
        G2.add_edge(from,to,1,needs[i][j]);
    }
    int lo=0,hi=300;
    while(hi-lo>1){
        int mid=(hi+lo)/2;
        mcf_graph<lint,lint> G3=G2;
        plint res=G3.flow(A+B,A+B+1,mid);
        if(res.se<=K && res.fi==mid) lo=mid;
        else hi=mid;
    }
    cout << lo << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 8616
final_rank: 19

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}

struct Primal_Dual{
    const int INF=(1<<30);
    struct edge{
        int to,cap,cost,rev;
    };
    vector<vector<edge>> G;
    vector<int> potential,min_cost,prevv,preve;
    Primal_Dual(int V):G(V){}
    void add_edge(int s,int t,int cap,int cost){
        G[s].push_back((edge){t,cap,cost,(int)(G[t].size())});
        G[t].push_back((edge){s,0,-cost,(int)(G[s].size()-1)});
    }
    int min_cost_flow(int s,int t,int f){
        int V=G.size(); int res=0;
        priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> pq;
        potential.assign(V,0);
        preve.assign(V,-1);
        prevv.assign(V,-1);
        while(f>0){
            min_cost.assign(V,INF);
            pq.push(make_pair(0,s));
            min_cost[s]=0;
            while(pq.size()){
                auto p=pq.top(); pq.pop();
                if(min_cost[p.second]<p.first)continue;
                int i=-1;
                for(auto &e:G[p.second]){
                    i++;
                    int nextcost=min_cost[p.second]+e.cost+potential[p.second]-potential[e.to];
                    if(e.cap>0 and min_cost[e.to]>nextcost){
                        min_cost[e.to]=nextcost;
                        prevv[e.to]=p.second;
                        preve[e.to]=i;
                        pq.push(make_pair(min_cost[e.to],e.to));
                    }
                }
            }
            if(min_cost[t]==INF)return -1; // 流せない
            for(int v=0;v<V;v++){
                potential[v]+=min_cost[v];
            }
            int Addflow=f;
            for(int v=t;v!=s;v=prevv[v]){
                Addflow=min(Addflow,G[prevv[v]][preve[v]].cap);
            }
            f-=Addflow;
            res+=Addflow*potential[t];
            for(int v=t;v!=s;v=prevv[v]){
                edge &e=G[prevv[v]][preve[v]];
                e.cap-=Addflow;
                G[v][e.rev].cap+=Addflow;
            }
        }
        return res;
    }
};

char a[211][211],b[211][211];

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int A,B,K; cin >> A >> B >> K;
    Primal_Dual G(A+B+2);
    int S=A+B,T=A+B+1;
    for(int i=0;i<A;i++){
        G.add_edge(S,i,1,0);
    }
    for(int i=0;i<B;i++){
        G.add_edge(A+i,T,1,0);
    }
    for(int i=0;i<A;i++){
        for(int j=0;j<B;j++){
            cin >> a[i][j];
        }
    }
    for(int i=0;i<B;i++){
        for(int j=0;j<A;j++){
            cin >> b[i][j];
        }
    }
    for(int i=0;i<A;i++){
        for(int j=0;j<B;j++){
            G.add_edge(i,A+j,1,(a[i][j]-'0')+(b[j][i]-'0'));
        }
    }
    int res=0;
    int sum=0;
    for(int i=1;i<=min(A,B);i++){
        int flow=G.min_cost_flow(S,T,1);
        if(flow==-1)break;
        sum+=flow;
        if(sum<=K )res=i;
        else break;
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 20
memory_kb: 4968
final_rank: 6

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

const int inf = 1000000000;

using namespace std;

struct MinimumCostFlow {
  typedef pair<int, int> P;

  struct edge {
    int to, cap, rev;
    int cost;
    edge(int a, int b, int c, int d): to(a), cap(b), rev(c), cost(d) {}
  };

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

  MinimumCostFlow(int v): G(v, vector<edge>()), prevv(v, 0), preve(v, 0), V(v) {}

  int add_edge(int from, int to, int cap, int cost) {
    int id = G[from].size();
    G[from].push_back(edge(to, cap, G[to].size(), cost));
    G[to].push_back(edge(from, 0, G[from].size() - 1, -cost));
    return id;
  }

  int solve(int s, int t, int f) {
    int res = 0;
    h.assign(V, 0);
    while (f > 0) {
      priority_queue<P, vector<P>, greater<P>> pq;
      dist.assign(V, inf);
      dist[s] = 0;
      pq.push(P(0, s));
      while (pq.size()) {
        P p = pq.top();
        pq.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];
          int d = dist[v] + e.cost + h[v] - h[e.to];
          if (e.cap > 0 && dist[e.to] > d) {
            dist[e.to] = d;
            prevv[e.to] = v;
            preve[e.to] = i;
            pq.push(P(dist[e.to], e.to));
          }
        }
      }
      if (dist[t] == inf) return -1;

      for (int v = 0; v < V; 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;
  }
};

#define SIZE 200


int main() {
  int A, B, K;
  int a[SIZE][SIZE], b[SIZE][SIZE];

  scanf("%d%d%d", &A, &B, &K);

  for (int i = 0; i < A; i++) {
    for (int j = 0; j < B; j++) {
      scanf("%1d", a[i] + j);
    }
  }

  for (int i = 0; i < B; i++) {
    for (int j = 0; j < A; j++) {
      scanf("%1d", b[j] + i);
    }
  }

  MinimumCostFlow flow(A + B + 2);

  int S = A + B;
  int T = S + 1;

  for (int i = 0; i < A; i++) flow.add_edge(S, i, 1, 0);
  for (int j = 0; j < B; j++) flow.add_edge(A + j, T, 1, 0);

  for (int i = 0; i < A; i++) {
    for (int j = 0; j < B; j++) {
      flow.add_edge(i, A + j, 1, a[i][j] + b[i][j]);
    }
  }

  int ans = 0;

  for (int i = 0; i < min(A, B); i++) {
    int res = flow.solve(S, T, 1);
    if (res < 0) break;
    if (K < res) break;
    ans++;
    K -= res;
  }

  printf("%d\n", ans);

  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 4948
final_rank: 7

code_snippet: #include <cassert>
#include <cstdio>
#include <vector>
#include <queue>
#include <utility>
#include <iostream>
#include <tuple>
#include <limits>
using namespace std;

struct MinCostFlowGraph {
private:
  using ll = long long;
  struct edge {
    int to;
    ll cap, cost;
    int r_idx;
    edge(int t, ll cap, ll cost, int r) :
      to(t), cap(cap), cost(cost), r_idx(r) {}
  };
  vector<vector<edge>> G;
  int sz;

public:
  MinCostFlowGraph(int n) : G(n), sz(n) {}

  void add_edge(int from, int to, ll cap, ll cost){
    int i = G[to].size(), i_ = G[from].size();
    G[from].emplace_back(to,cap,cost,i);
    G[to].emplace_back(from,0,-cost,i_);
  }
  
  ll solve(int from, int to, ll k){
    ll f = 0, cost_sum = 0;
    const ll INF = numeric_limits<ll>::max();
    vector<ll> potential(sz);
    while(1){
      vector<ll> dist(sz,INF);
      dist[from] = 0;
      vector<int> prev_v(sz,-1);
      vector<int> prev_e(sz,-1);
      priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<>> pq;
      pq.emplace(0,from);
      while(pq.size()){
        // auto [d, v] = pq.top();
        ll d = pq.top().first;
        ll v = pq.top().second;
        // d *= -1;
        pq.pop();
        if(dist[v] < d) continue;
        for(size_t i = 0; i < G[v].size(); ++i){
          const auto& e = G[v][i];
          if(e.cap == 0) continue;
          int v_ = e.to;
          ll d_ = d + e.cost + potential[v] - potential[v_];
          if(dist[v_] <= d_)
            continue;
          dist[v_] = d_;
          prev_v[v_] = v;
          prev_e[v_] = i;
          // pq.emplace(-d_,e.to);
          pq.emplace(d_,e.to);
        }
      }
      if(dist[to] >= INF) return f;
      for(int i = 0; i < sz; ++i)
        potential[i] += dist[i];
      int v = to;
      ll flow = 1;
      while(v != from){
        int v_ = prev_v[v];
        flow = min(flow,G[v_][prev_e[v]].cap);
        v = v_;
      }
      v = to;
      ll diff = 0;
      while(v != from){
        int v_ = prev_v[v];
        auto& e = G[v_][prev_e[v]];
        e.cap -= flow;
        diff += flow*e.cost;
        G[v][e.r_idx].cap += flow;
        v = v_;
      }
      if(cost_sum+diff > k)
        return f;
      f += flow;
      cost_sum += diff;
    }
    return f;
  }
};

int main(){
  int a, b, k;
  cin >> a >> b >> k;
  MinCostFlowGraph G(a+b+2);
  vector<vector<int>> E(a,vector<int>(b));
  for(int i = 0; i < a; ++i){
    string s;
    cin >> s;
    for(int j = 0; j < b; ++j){
      int c = s[j] - '0';
      E[i][j] += c;
    }
  }
  for(int j = 0; j < b; ++j){
    string s;
    cin >> s;
    for(int i = 0; i < a; ++i){
      int c = s[i] - '0';
      E[i][j] += c;
    }
  }
  for(int i = 0; i < a; ++i)
    for(int j = 0; j < b; ++j)
      G.add_edge(i,a+j,1,E[i][j]);
  int s = a+b, t = s+1;
  for(int i = 0; i < a; ++i)
    G.add_edge(s,i,1,0);
  for(int j = 0; j < b; ++j)
    G.add_edge(a+j,t,1,0);
  cout << G.solve(s,t,k) << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 6396
final_rank: 13

code_snippet: #include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <complex>
#include <cmath>
#include <limits>
#include <climits>
#include <ctime>
#include <cassert>
#include <numeric>
#include <functional>
#include <bitset>

using namespace std;
using lint = long long int;
long long int INF = 1001001001001001LL;
int inf = 1000000007;
long long int MOD = 1000000007LL;
double PI = 3.1415926535897932;

template<typename T1,typename T2>inline void chmin(T1 &a,const T2 &b){if(a>b) a=b;}
template<typename T1,typename T2>inline void chmax(T1 &a,const T2 &b){if(a<b) a=b;}

#define ALL(a) a.begin(),a.end()
#define RALL(a) a.rbegin(),a.rend()

/* do your best */

// 最小費用流
// O(F E log V)
// 与えられるもの
// 有向グラフ G = (V, E)
// 各辺 e に対して, 容量 u(e) >= 0
// 各辺 e に対して, 費用 c(e) (負でも ok)

// 使い方
// PrimalDual(V) (コンストラクタ)
// add_edge(int from, int to, flow_t cap, cost_t cost)
// cost に関する負の閉路が存在する場合,だめ
// veryfied : http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_6_B&lang=jp
// 流れなかったら -1 を返す



template< typename flow_t, typename cost_t >
struct PrimalDual{
    const cost_t INF;

    struct edge {
        int to;
        flow_t cap;
        cost_t cost;
        int rev;
        bool isrev;
    };
    vector<vector<edge>> graph;
    vector<cost_t> potential, min_cost;
    vector<int> prevv, preve;

    PrimalDual(int V) : graph(V), INF(numeric_limits< cost_t >::max()){}

    void add_edge(int from, int to, flow_t cap, cost_t cost){
        graph[from].emplace_back((edge) {to, cap, cost, (int)graph[to].size(), false});
        graph[to].emplace_back((edge) {from, 0, -cost, (int)graph[from].size() - 1, true});
    }

    cost_t min_cost_flow(int s, int t, flow_t f){
        int V = (int) graph.size();
        cost_t ret = 0;
        using Pi = pair< cost_t, int >;
        priority_queue< Pi, vector< Pi >, greater< Pi > > que;
        potential.assign(V, 0);
        preve.assign(V, -1);
        prevv.assign(V, -1);

        while(f > 0){
            min_cost.assign(V, INF);
            que.emplace(0, s);
            min_cost[s] = 0;
            while(!que.empty()){
                Pi p = que.top();
                que.pop();
                if(min_cost[p.second] < p.first) continue;
                for(int i = 0; i < graph[p.second].size(); i++){
                    edge &e = graph[p.second][i];
                    cost_t nextCost = min_cost[p.second] + e.cost + potential[p.second] - potential[e.to];
                    if(e.cap > 0 && min_cost[e.to] > nextCost){
                        min_cost[e.to] = nextCost;
                        prevv[e.to] = p.second, preve[e.to] = i;
                        que.emplace(min_cost[e.to], e.to);
                    }
                }
            }
            if(min_cost[t] == INF) return -1;
            for(int v = 0; v < V; v++) potential[v] += min_cost[v];
            flow_t addflow = f;
            for(int v = t; v != s; v = prevv[v]){
                addflow = min(addflow, graph[prevv[v]][preve[v]].cap);
            }
            f -= addflow;
            ret += addflow * potential[t];
            for(int v = t; v != s; v = prevv[v]){
                edge &e = graph[prevv[v]][preve[v]];
                e.cap -= addflow;
                graph[v][e.rev].cap += addflow;
            }
        }
        return ret;
    }

    void output(){
        for(int i = 0; i < graph.size(); i++){
            for(auto &e : graph[i]) {
                if(e.isrev) continue;
                auto &rev_e = graph[e.to][e.rev];
                cout << i << "->" << e.to << " (flow: " << rev_e.cap << "/" << rev_e.cap + e.cap << ")" << endl;
            }
        }
    }
};

int main() {

  lint A, B, K; cin >> A >> B >> K;
  vector<string> a(A);
  for (int i = 0; i < A; i++) {
    cin >> a[i];
  }
  vector<string> b(B);
  for (int i = 0; i < B; i++) {
    cin >> b[i];
  }
  

  // cost が k 以下の中の最大の F
  int ok = 0;
  int ng = min(A, B) + 1;
  while (ng - ok > 1) {
    int mid = (ok + ng) / 2;
    PrimalDual<int, int> pd(A + B + 2);
    int source = A + B;
    int sink = A + B + 1;

    for (int i = 0; i < A; i++) {
      int from = source;
      int to = i;
      pd.add_edge(from, to, 1, 0);
    }

    for (int i = 0; i < B; i++) {
      int from = A + i;
      int to = sink;
      pd.add_edge(from, to, 1, 0);
    }

    for (int i = 0; i < A; i++) {
      for (int j = 0; j < B; j++) {
        int from = i;
        int to = j + A;
        int cap = 1;
        int cost = 0;
        if (a[i][j] == '1') cost++;
        if (b[j][i] == '1') cost++;
        pd.add_edge(from, to, cap, cost);
      }
    }

    int cost = pd.min_cost_flow(source, sink, mid);

    if (cost <= K) {
      ok = mid;
    } else {
      ng = mid;
    }
  }

  cout << ok << endl;


  return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 5192
final_rank: 12

code_snippet: // #define _GLIBCXX_DEBUG // for STL debug (optional)
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <string>
#include <cstring>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <complex>
#include <cmath>
#include <limits>
#include <cfloat>
#include <climits>
#include <ctime>
#include <cassert>
#include <numeric>
#include <fstream>
#include <functional>
#include <bitset>
using namespace std;
using ll = long long int;
using int64 = long long int;
 
template<typename T> void chmax(T &a, T b) {a = max(a, b);}
template<typename T> void chmin(T &a, T b) {a = min(a, b);}
template<typename T> void chadd(T &a, T b) {a = a + b;}
 
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
const int INF = 1LL << 29;
const ll LONGINF = 1LL << 60;
const ll MOD = 1000000007LL;

// Ford-Fulkerson 法による 最大流 O( F |E| )
// Bellman-Ford 法による 最小費用流 O( F |V| |E| )
// [条件に注意] Dijkstra 法による 最小費用流 O( F |E| log |V| )

template <typename CapTp=int, typename CostTp=int>
struct Edge {
    int to, rev;
    CapTp cap; CostTp cost;
    bool is_rev;
    Edge(int t, bool f, int r, CapTp ca, CostTp co=0)
        : to(t), rev(r), cap(ca), cost(co), is_rev(f) {}
};

template <typename CapTp=int, typename CostTp=int>
struct Flow {
    using Graph = vector< vector< Edge<CapTp, CostTp> > >;
    Graph G; const CapTp IA; const CostTp IO;
    vector< pair<int, int> > r_edges;
    Flow(int N_, CapTp IA_=1<<29, CostTp IO_=1<<29)
        : G(N_), IA(IA_), IO(IO_), r_edges() {}
    // 辺を追加 (from -> to に流量 ca, コスト co)
    void add_edge(int from, int to, CapTp ca, CostTp co=0) {
        G[from].emplace_back(to, false, G[to].size(), ca, co);
        G[to].emplace_back(from, true, G[from].size() - 1, 0, -co);
        r_edges.emplace_back(to, G[to].size() - 1);
    }
    // k 番目の辺にいくつ流れたか
    CapTp get_flowed_cap(size_t k) {
        if(r_edges.size() <= k) return -1;
        int v, i; tie(v, i) = r_edges[k];
        return G[v][i].cap;
    }
    // s -> t 最大流
    CapTp max_flow(int s, int t) {
        vector<bool> used(G.size());
        auto dfs = [&](auto &&func, int v, int t, CapTp f) -> CapTp {
            if(v == t) return f;
            used[v] = true;
            for(auto &e : G[v]) {
                if(used[e.to] or e.cap == 0) continue;
                CapTp d = func(func, e.to, t, min(f, e.cap));
                if(d == 0) continue;
                e.cap -= d; G[e.to][e.rev].cap += d;
                return d;
            }
            return 0;
        };

        CapTp res(0);
        while(true) {
            fill(used.begin(), used.end(), false);
            CapTp delta = dfs(dfs, s, t, IA);
            if(delta == 0) return res;
            res += delta;
        }
    }
    // ベルマンフォードをつかって最小費用流
    CostTp mincost_flow(int s, int t, CapTp f) {
        vector<CostTp> dist(G.size()); CostTp res(0);
        vector<int> prevv(G.size()), preve(G.size());
        while(f > 0) {
            fill(dist.begin(), dist.end(), IO);
            dist[s] = 0;
            while(1) {
                bool upd = false;
                for(int v=0; v<(int)G.size(); v++) {
                    if(dist[v] == IO) continue;
                    for(size_t i=0; i<G[v].size(); i++) {
                        auto &e = G[v][i];
                        if(e.cap == 0 or dist[e.to] <= dist[v] + e.cost) continue;
                        dist[e.to] = dist[v] + e.cost;
                        prevv[e.to] = v, preve[e.to] = i;
                        upd = true;
                    }
                }
                if(!upd) break;
            }

            if(dist[t] == IO) return -1;
            CapTp 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]) {
                auto &e = G[prevv[v]][preve[v]];
                e.cap -= d, G[v][e.rev].cap += d;
            }
        }
        return res;
    }
    // ポテンシャルの導入により、ダイクストラ法で最小費用流を解く
    // [仮定している条件]
    //     1. グラフに負の閉路が存在しない (流量の 0 初期化のため)
    //        もし存在するならベルマンフォードで負の閉路を見つけ
    //        そこに流せるだけ流してスタート
    //     2. グラフに負の辺が存在しない (pot_0 の計算可能性)
    //        もし存在する場合は最初のみベルマンフォードを使う必要あり
    CostTp fast_mincost_flow(int s, int t, CapTp f) {
        CostTp res = 0;
        vector<CostTp> dist(G.size()), pot(G.size());
        vector<int> prevv(G.size()), preve(G.size());
        while(f > 0) {
            using PT = pair<CostTp, int>;
            priority_queue< PT, vector<PT>, greater<PT> > que;
            fill(dist.begin(), dist.end(), IO);

            dist[s] = 0;
            que.push(make_pair(0, s));
            while(!que.empty()) {
                PT cur = que.top(); que.pop();
                int v = cur.second;
                if(dist[v] < cur.first) continue;
                for(size_t i=0; i<G[v].size(); i++) {
                    auto& e = G[v][i];
                    if(e.cap > 0 and dist[e.to] > dist[v] + e.cost + pot[v] - pot[e.to]) {
                        dist[e.to] = dist[v] + e.cost + pot[v] - pot[e.to];
                        prevv[e.to] = v;
                        preve[e.to] = i;
                        que.push(make_pair(dist[e.to], e.to));
                    }
                }
            }
            if(dist[t] == IO) {
                return INF;
            }
            for(int v=0; v<(int)G.size(); v++) pot[v] += dist[v];

            CapTp d = f;
            for(int v=t; v!=s; v=prevv[v]) {
                d = min(d, G[prevv[v]][preve[v]].cap);
            }
            f -= d;
            res += d * pot[t];
            for(int v=t; v!=s; v=prevv[v]) {
                auto& e = G[prevv[v]][preve[v]];
                e.cap -= d;
                G[v][e.rev].cap += d;
            }
        }
        return res;
    }    
};


int main() {
    int A, B, K; cin >> A >> B >> K;
    vector<string> X(A), Y(B);
    for(int i=0; i<A; i++) cin >> X[i];
    for(int i=0; i<B; i++) cin >> Y[i];

    Flow<> fl(A + B + 2);
    int source = A + B, sink = source + 1;
    for(int i=0; i<A; i++) fl.add_edge(source, i, 1, 0);
    for(int i=0; i<B; i++) fl.add_edge(A+i, sink, 1, 0);
    
    for(int i=0; i<A; i++) {
        for(int j=0; j<B; j++) {
            int cnt = 0;
            if(X[i][j] == '1') cnt++;
            if(Y[j][i] == '1') cnt++;
            // fprintf(stderr, "i = %d, j = %d, cnt = %d\n", i, j, cnt);
            fl.add_edge(i, A+j, 1, cnt);
        }
    }

    int ub = min(A, B) + 1, lb = 0;
    while(ub - lb > 1) {
        Flow<> fl_ = fl;
        int mid = (ub + lb) / 2;
        int res = fl_.fast_mincost_flow(source, sink, mid);
        // fprintf(stderr, "mid = %d, res = %d\n", mid, res);
        if(res <= K) lb = mid;
        else ub = mid;
    }
    cout << lb << endl;
    return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 7464
final_rank: 18

code_snippet: #include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int INF = 1e9;
const ll LINF = 1e18;
template<class S,class T> ostream& operator << (ostream& out,const pair<S,T>& o){ out << "(" << o.first << "," << o.second << ")"; return out; }
template<class T> ostream& operator << (ostream& out,const vector<T> V){ for(int i = 0; i < V.size(); i++){ out << V[i]; if(i!=V.size()-1) out << " ";} return out; }
template<class T> ostream& operator << (ostream& out,const vector<vector<T> > Mat){ for(int i = 0; i < Mat.size(); i++) { if(i != 0) out << endl; out << Mat[i];} return out; }
template<class S,class T> ostream& operator << (ostream& out,const map<S,T> mp){ out << "{ "; for(auto it = mp.begin(); it != mp.end(); it++){ out << it->first << ":" << it->second; if(mp.size()-1 != distance(mp.begin(),it)) out << ", "; } out << " }"; return out; }

/*
 <url:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2776>
 問題文============================================================
 =================================================================
 解説=============================================================
 ================================================================
 */
typedef ll PD_Type;
const PD_Type PD_INF = INF;
struct Primal_Dual
{
    typedef pair< PD_Type, int > pii;
    
    struct edge
    {
        int to, rev;
        PD_Type    cap, cost;
        edge() {}
        edge(int to, PD_Type cap, PD_Type cost, int rev) :to(to), cap(cap), cost(cost), rev(rev) {}
        
    };
    vector< vector< edge > > graph;
    vector< int > prevv, preve;
    vector< PD_Type > potential, min_cost;
    Primal_Dual(int V) : graph(V) {}
    
    void add_edge(int from, int to, PD_Type cap, PD_Type cost)
    {
        graph[from].push_back(edge(to, cap, cost, (int)graph[to].size()));
        graph[to].push_back(edge(from, 0, -cost, (int)graph[from].size() - 1));
    }
    
    PD_Type min_cost_flow(int s, int t, int f)
    {
        int V = (int)graph.size();
        PD_Type ret = 0;
        priority_queue< pii, vector< pii >, greater< pii > > que;
        potential.assign(V, 0);
        preve.assign(V, -1);
        prevv.assign(V, -1);
        
        while (f > 0) {
            min_cost.assign(V, PD_INF);
            que.push(pii(0, s));
            min_cost[s] = 0;
            
            while (!que.empty()) {
                pii p = que.top();
                que.pop();
                if (min_cost[p.second] < p.first) continue;
                for (int i = 0; i < (int)graph[p.second].size(); i++) {
                    edge &e = graph[p.second][i];
                    PD_Type nextCost = min_cost[p.second] + e.cost + potential[p.second] - potential[e.to];
                    if (e.cap > 0 && min_cost[e.to] > nextCost) {
                        min_cost[e.to] = nextCost;
                        prevv[e.to] = p.second; preve[e.to] = i;
                        que.push(pii(min_cost[e.to], e.to));
                    }
                }
            }
            if (min_cost[t] == PD_INF) return -1;
            for (int v = 0; v < V; v++) potential[v] += min_cost[v];
            PD_Type addflow = f;
            for (int v = t; v != s; v = prevv[v]) {
                addflow = min(addflow, graph[prevv[v]][preve[v]].cap);
            }
            f -= addflow;
            ret += addflow * potential[t];
            for (int v = t; v != s; v = prevv[v]) {
                edge &e = graph[prevv[v]][preve[v]];
                e.cap -= addflow;
                graph[v][e.rev].cap += addflow;
            }
        }
        return ret;
    }
};

void solve() {
    int A, B, K; cin >> A >> B >> K;
    vector<string> a(A), b(B);
    for (auto& in : a) cin >> in;
    for (auto& in : b) cin >> in;
    
    int S = A + B, T = A + B + 1;
    Primal_Dual clojure(A + B + 2);
    for (int i = 0; i < A; i++) clojure.add_edge(S, i, 1, 0);
    for (int i = 0; i < B; i++) clojure.add_edge(A+i, T, 1, 0);
    
    for (int i = 0; i < A; i++) {
        for (int j = 0; j < B; j++) {
            ll cost = 0;
            if (a[i][j] == '1') cost++;
            if (b[j][i] == '1') cost++;
            clojure.add_edge(i, A + j, 1, cost);
        }
    }
    
    ll ans = 0;
    while (true) {
        ll ret = clojure.min_cost_flow(S, T, 1);
        if (ret == -1) break;
        if (ret > K) break;
        K -= ret;
        ans++;
    }
    cout << ans << endl;
}

int main() {
    cin.tie(0); ios_base::sync_with_stdio(false);
    solve();
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 5540
final_rank: 10

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 410


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];


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));
}

int min_cost_flow(int source,int sink,int flow){
	int ret = 0;
	while(flow > 0){

		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;
						pre_node[e.to] = node_id;
						pre_edge[e.to] = i;
						update = true;
					}
				}
			}
		}

		if(dist[sink] == BIG_NUM){
			return -1;
		}

		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 A,B,K;
	scanf("%d %d %d",&A,&B,&K);

	char table_1[A][B+1],table_2[B][A+1];
	int cost[A][B];

	for(int i = 0; i < A; i++){
		scanf("%s",table_1[i]);
	}

	for(int i = 0; i < B; i++){
		scanf("%s",table_2[i]);
	}

	for(int i = 0; i < A; i++){
		for(int k = 0; k < B; k++){
			cost[i][k] = (table_1[i][k]-'0')+(table_2[k][i]-'0');
		}
	}

	int source = 0,sink = 1,index = 2;
	int index_A[A],index_B[B];

	for(int i = 0; i < A; i++){
		index_A[i] = index++;
		add_edge(source,index_A[i],1,0);
	}

	for(int i = 0; i < B; i++){
		index_B[i] = index++;
		add_edge(index_B[i],sink,1,0);
	}

	for(int i = 0; i < A; i++){
		for(int k = 0; k < B; k++){
			add_edge(index_A[i],index_B[k],1,cost[i][k]);
		}
	}

	int ans = 0,add_cost;
	int sum_cost = 0;

	V = index;

	while(sum_cost <= K){
		add_cost = min_cost_flow(source,sink,1);

		if(add_cost < 0)break;

		if(sum_cost+add_cost <= K){
			sum_cost += add_cost;
			ans++;
			if(ans == min(A,B))break;
		}else{
			break;
		}
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 4932
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define GET_MACRO(_1, _2, _3, NAME, ...) NAME
#define _repl(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
#define _rep(i,n) _repl(i,0,n)
#define rep(...) GET_MACRO(__VA_ARGS__, _repl, _rep)(__VA_ARGS__)
#define mp(a,b) make_pair((a),(b))
#define pb(a) push_back((a))
#define all(x) (x).begin(),(x).end()
#define uniq(x) sort(all(x)),(x).erase(unique(all(x)),end(x))
#define fi first
#define se second
#define dbg(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
void _dbg(string){cout<<endl;}
template<class H,class... T> void _dbg(string s,H h,T... t){int l=s.find(',');cout<<s.substr(0,l)<<" = "<<h<<", ";_dbg(s.substr(l+1),t...);}
template<class T,class U> ostream& operator<<(ostream &o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream &o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

#define INF 1120000000

template<typename T>
class MinCostFlow{
private:
  struct edge{int to; T cap, cost; int rev;};
  using P = pair<T,int>;
  vector<vector<edge> > Graph;
  vector<int> prevv, preve;
  vector<T> h, d; // ??????????????£?????????????????¢
public:
  MinCostFlow(int v){
    // ????????°v??§?????????
    Graph.resize(v);
    prevv.resize(v);
    preve.resize(v);
    h.resize(v);
    d.resize(v);
  }
  T min_cost_flow(int s, int t, T f){
    T res = 0;
    fill(all(h), 0);
    // ??????????????????????????¨???
    // rep(v,Graph.size()){
    //   rep(j,Graph[v].size()){
    //     edge &e = Graph[v][j];
    //     if(e.cap==0) continue;
    //     int u = e.to;
    //     h[u] = min(h[u],h[v]+e.cost);
    //   }
    // }
    while(f>0){
      priority_queue<P, vector<P>, greater<P>> pq;
      fill(all(d), INF);
      d[s] = 0;
      pq.push(mp(0,s));
      while(!pq.empty()){
        auto p = pq.top(); pq.pop();
        int v = p.se;
        if(d[v] < p.fi) continue;
        rep(i,Graph[v].size()){
          edge &e = Graph[v][i];
          if(e.cap > 0 && d[e.to] > d[v] + e.cost + h[v] - h[e.to]){
            d[e.to] = d[v] + e.cost + h[v] - h[e.to];
            prevv[e.to] = v;
            preve[e.to] = i;
            pq.push(mp(d[e.to], e.to));
          }
        }
      }
      if(d[t] == INF) return -1;
      rep(i,Graph.size()) h[i] += d[i];

      T nf = f;
      for(int v=t; v!=s; v = prevv[v]){
        nf = min(nf, Graph[prevv[v]][preve[v]].cap);
      }
      f -= nf;
      res += nf * h[t];
      for(int v=t; v!=s; v=prevv[v]){
        edge &e = Graph[prevv[v]][preve[v]];
        e.cap -= nf;
        Graph[v][e.rev].cap += nf;
      }
    }
    return res;
  }
  void add_edge(int from ,int to, T cap, T cost){
    Graph[from].pb(((edge){to, cap, cost, (int)Graph[to].size()}));
    Graph[to].pb(((edge){from, 0, -cost, (int)Graph[from].size()-1}));
  }
};

int main(){
  int a,b,k;
  cin>>a>>b>>k;

  vector<string> va(a), vb(b);
  rep(i,a) cin>>va[i];
  rep(i,b) cin>>vb[i];

  MinCostFlow<int> flow(a+b+2);
  int s = a+b;
  int t = a+b+1;

  rep(i,a) rep(j,b){
    int cost = va[i][j] + vb[j][i] -'0'*2;
    flow.add_edge(i, a+j, 1, cost);
  }
  rep(i,a) flow.add_edge(s, i, 1, 0);
  rep(i,b) flow.add_edge(a+i, t, 1, 0);

  int crnt = 0;
  int totalcost = 0;
  while(true){
    int nv = flow.min_cost_flow(s, t, 1);
    if(nv == -1 || totalcost+nv > k) break;
    totalcost += nv;
    crnt++;
  }
  cout << crnt << endl;

  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 4784
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

using pi = pair<int,int>;

// (ティツ。ツ古」ツ?催・ツ?? テ・ツョツケテゥツ?? テ」ツつウテ」ツつケテ」ツδ? テゥツ??ィツセツコ)
struct edge{ int to,cap,cost,rev; };

int V; // TODO:initialize
const int MAX_V = 444; // TODO:initialize
const int INF = 19191919; // TODO:initialize
vector<edge> G[MAX_V];
int h[MAX_V]; // テ」ツδ敕」ツδ?」ツδウテ」ツつキテ」ツδ」テ」ツδォ
int dist[MAX_V];
int prevv[MAX_V], preve[MAX_V]; // テァツ崢エテ・ツ可催」ツ?ョテゥツ?づァツつケテ」ツ?ィティツセツコ

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

// sテ」ツ?凝」ツつ液テ」ツ?クテ」ツ?ョテヲツオツ?ゥツ?叔テ」ツ?ョテヲツ慊?・ツーツ湘ィツイツサテァツ板ィテヲツオツ?テ、ツクツ催・ツ渉ッティツδステ」ツ?ェテ」ツつ?1)
int min_cost_flow(int s, int t, int f, bool neg = false){
    int res = 0;
    fill(h,h+V,0);
    while(f>0){
        priority_queue<pi,vector<pi>,greater<pi>> pq;
        fill(dist,dist+V,INF);
        dist[s]=0;
        if(neg)
        {
            // bellman-fordテ」ツ?ァhテ」ツつ津ヲツ崢エテヲツ鳴ー
            neg = false;
            bool update;
            do{
                update = false;
                rep(v,V){
                    if(dist[v] == INF) continue;
                    rep(i,G[v].size()){
                        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;
                        }
                    }
                }
            }while(update);
        }
        else
        {
            // dijkstraテ」ツ?ァhテ」ツつ津ヲツ崢エテヲツ鳴ー
            pq.push(pi(0,s));
            while(!pq.empty()){
                pi p = pq.top();
                pq.pop();
                int v = p.se;
                if(p.fi>dist[v]) 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;
                        pq.push(pi(dist[e.to],e.to));
                    }
                }
            }
        }

        // テ」ツ?禿」ツつ古、ツサツ・テ、ツクツ甘ヲツオツ?」ツ?崚」ツ?ェテ」ツ??
        if(dist[t]==INF) return -1;

        rep(v,V) h[v] += dist[v];

        // s-tテゥツ鳴禿」ツ?ョテヲツ慊?ァツ淞ュティツキツッテ」ツ?ォテヲツイツソテ」ツ?」テ」ツ?ヲテァツ崢ョテ、ツクツ?ヲツ敖ッテヲツオツ?」ツ??
        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 A,B,K;
    cin >>A >>B >>K;

    V = A+B+2;

    vector<string> a(A),b(B);
    rep(i,A) cin >>a[i];
    rep(i,B) cin >>b[i];

    int S = A+B, T = S+1;
    rep(i,A) add_edge(S,i,1,0);
    rep(i,B) add_edge(A+i,T,1,0);

    rep(i,A)rep(j,B)
    {
        int cost = 0;
        cost += a[i][j]-'0';
        cost += b[j][i]-'0';
        add_edge(i,A+j,1,cost);
    }

    int total = 0;
    int ans = 0;
    while(1)
    {
        int F = min_cost_flow(S,T,1);
        if(F==-1) break;

        total += F;
        if(total>K) break;
        ++ans;
    }

    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 4796
final_rank: 1

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
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 int amax,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 = amax; 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) {
	assert(weight >= 0);//????????¨?????°??????
	g[from].push_back(Edge(from, to, cap, weight));
}

int main() {
	int A, B, K; cin >> A >> B >> K;
	vector<vector<int>>costs(A, vector<int>(B));
	for (int i = 0; i < A; ++i) {
		string st; cin >> st;
		for (int j = 0; j < B; ++j) {
			auto c = st[j] != '1';
			if (c == 0)costs[i][j] += 1;
		}
	}
	for (int i = 0; i < B; ++i) {
		string st; cin >> st;
		for (int j = 0; j < A; ++j) {
			auto c = st[j]!= '1';
			if (c == 0)costs[j][i] += 1;
		}
	}

	const int start = 0;
	const int aa = start + 1;
	const int bb=aa+A;
	const int goal = bb + B;
	Graph g(goal + 1);
	for (int i = 0; i < A; ++i) {
		g[start].push_back(Edge(start, aa + i, 1, 0));
	}
	for (int i = 0; i < A; ++i) {
		for (int j = 0; j < B; ++j) {
			g[aa + i].push_back(Edge(aa + i, bb + j, 1, costs[i][j]));
		}
	}
	for (int j = 0; j < B; ++j) {
		g[bb + j].push_back(Edge(bb + j, goal, 1, 0));
	}
	int amin = 0;
	int amax = min(A,B)+1;
	while (amin + 1 != amax) {
		int amid = (amin + amax) / 2;
		auto p = minimumCostFlow(amid, g, start, goal);
		if (minimumCostFlow(amid, g, start, goal).first <=K) {
			amin = amid;
		}
		else {
			amax = amid;
		}
	}
	cout << amin << endl;
	return 0;
}
accuracy: 1
time_ms: 690
memory_kb: 8064
final_rank: 20

code_snippet: #include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=(a);i<(int)(b);i++)
#define rep(i,a) FOR(i,0,a)
#define all(a) (a).begin(),(a).end()
#define pb push_back
#define sz size()
#define MP make_pair
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vi;

const int INF = 1e8;

struct edge{
  int from, to, cost, cap, rev;
  edge(int a, int b, int c, int d, int e)
    :from(a), to(b), cost(c), cap(d), rev(e) {}
};


struct minFlow{
  int v;
  vector< vector<edge> > graph;
  vi d, use, h, pv, pe;

  minFlow(int n):v(n){
    graph.resize(v);
    pv.resize(v); pe.resize(v);
  }

  void add(int s, int g, int c, int p){
    graph[s].pb(edge(s,g,c,p,graph[g].sz));
    graph[g].pb(edge(g,s,-c,0,graph[s].sz-1));
  }

  int maxFlow(int s, int t, int k){
    int res = 0, cost = 0;
    h = vi(v,0);

    while(1){
      int f = 1;
      priority_queue< pii, vector<pii>, greater<pii> > q;
      d = vi(v,INF);
      d[s] = 0; q.push(MP(0,s));
      
      while(q.sz){
	pii p = q.top(); q.pop();
	int u = p.second;
	if(d[u] < p.first) continue;
	rep(i, graph[u].sz){
	  edge &e = graph[u][i];
	  if(e.cap>0 && d[e.to] > d[u] + e.cost + h[u] - h[e.to]){
	    d[e.to] = d[u] + e.cost + h[u] - h[e.to];
	    pv[e.to] = u; pe[e.to] = i;
	    q.push( MP(d[e.to], e.to) );
	  }
	}
      }
      if(d[t] == INF) break;
      rep(u,v) h[u] += d[u];
      
      int x = f;
      for(int u=t;u!=s;u=pv[u]) x = min(x, graph[pv[u]][pe[u]].cap);
      f -= x;
      cost += x*h[t];

      if(cost>k) break;
      res++;
      for(int u=t;u!=s;u=pv[u]){
	edge &e = graph[pv[u]][pe[u]];
	e.cap -= x; graph[u][e.rev].cap += x;
      }

    }

    return res;
  }
};

int main(){
  int a,b,k;
  cin >> a >> b >> k;

  int n = a+b+2;
  int S = a+b, T = S+1;
  minFlow mf(n);

  vector<vi> w(a, vi(b,0));

  rep(i,a){
    string x; cin >> x;
    rep(j,b){
      if(x[j] == '1') w[i][j]++;
    }
  }

  rep(i,b){
    string x; cin >> x;
    rep(j,a){
      if(x[j] == '1') w[j][i]++;
    }
  }

  rep(i,a)rep(j,b){
    mf.add(i,j+a,w[i][j],1);
  }

  rep(i,a) mf.add(S,i,0,1);
  rep(i,b) mf.add(i+a,T,0,1);

  cout << mf.maxFlow(S,T,k) << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 5328
final_rank: 9

code_snippet: #include<bits/stdc++.h>
using namespace std;
 
#define int long long
typedef pair<int,int>pint;
typedef vector<int>vint;
typedef vector<pint>vpint;
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(v) (v).begin(),(v).end()
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
template<class T,class U>inline void chmin(T &t,U f){if(t>f)t=f;}
template<class T,class U>inline void chmax(T &t,U f){if(t<f)t=f;}
 
struct edge{
    int to,cap,cost,rev;
    edge(int to,int cap,int cost,int rev):to(to),cap(cap),cost(cost),rev(rev){}
};
 
const int INF=1001001001;
const int MAX_V=500;
int S=MAX_V-2,T=MAX_V-1;
vector<edge>G[MAX_V];
int dist[MAX_V];
int prevv[MAX_V],preve[MAX_V];
 
void init(){
    rep(i,MAX_V)G[i].clear();
}
void add_edge(int from,int to,int cap,int cost){
    G[from].pb(edge(to,cap,cost,G[to].size()));
    G[to].pb(edge(from,0,-cost,G[from].size()-1));
}
 
int min_cost_flow(int s,int t,int f){
    int res=0;
    while(f>0){
        fill_n(dist,MAX_V,INF);
        dist[s]=0;
        bool update=true;
        while(update){
            update=false;
            rep(v,MAX_V){
                if(dist[v]==INF)continue;
                rep(i,G[v].size()){
                    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]){
            chmin(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 A,B,K;
string a[200],b[200];
signed main(){
    cin>>A>>B>>K;
    rep(i,A)cin>>a[i];
    rep(i,B)cin>>b[i];
 
    int lb=0,ub=300;
    while(ub-lb>1){
        int mid=(ub+lb)/2;
 
        init();
        rep(i,A)add_edge(S,i,1,0);
        rep(i,B)add_edge(i+A,T,1,0);
        rep(i,A)rep(j,B){
            int cnt=0;
            if(a[i][j]=='1')cnt++;
            if(b[j][i]=='1')cnt++;
            add_edge(i,j+A,1,cnt);
        }
 
        int tmp=min_cost_flow(S,T,mid);
        if(tmp==-1||tmp>K)ub=mid;
        else lb=mid;
    }
    cout<<lb<<endl;
    return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 6496
final_rank: 16

code_snippet: #include<stdio.h>
#include<iostream>
#include<fstream>
#include<string>
#include<vector>
#include<list>
#include<map>
#include<math.h>
#include<algorithm>
using namespace std;

class MatrixIndex :public pair<int, int>
{
public:
	MatrixIndex(int i, int j) :pair<int, int>(i, j){
	}
};

class Matrix :public vector< vector<char> >
{
public:
	Matrix(int col, int row)
	{
		resize(col);
		for (size_t i = 0; i < size(); ++i)
		{
			vector<char> & t = (*this)[i];
			t.resize(row);
		}
	}
};


class Keys //: public string
{
public:
	string keys;
	Keys(const Keys &_key) :keys(_key.keys)
	{

	}
	Keys(Matrix & c, list<int> & is, list<int> & js)
	{
		list<pair<int,int> > sorted_is;
		for (list<int>::iterator it = is.begin(); it != is.end(); ++it)
		{
			pair<int, int> sum(0,*it);
			for (list<int>::iterator jt = js.begin(); jt != js.end(); ++jt)
			{
				sum.first += c[*it][*jt];
			}
			sorted_is.push_back(sum);
		}
		sorted_is.sort();

		list<pair<int, int> > sorted_js;
		for (list<int>::iterator jt = js.begin(); jt != js.end(); ++jt)
		{
			pair<int, int> sum(0, *jt);
			for (list<int>::iterator it = is.begin(); it != is.end(); ++it)
			{
				sum.first += c[*it][*jt];
			}
			sorted_js.push_back(sum);
		}
		sorted_js.sort();

		keys.resize((sorted_js.size() + 1) * sorted_is.size());
		int i = 0;
		for (list<pair<int, int> >::iterator it = sorted_is.begin(); it != sorted_is.end(); ++it)
		{
			for (list<pair<int, int> >::iterator jt = sorted_js.begin(); jt != sorted_js.end(); ++jt)
			{
				keys[i++] = c[it->second][jt->second] + '0';
			}
			keys[i++] = '_';
		}
	}
};






void normalize_two(Matrix & c, list<int> & is, list<int> & js, list<MatrixIndex> & twos)
{
	//???
	list<int> is2;
	for (list<int>::iterator it = is.begin(); it != is.end(); ++it)
	{
		int & i = *it;
		bool b_ok = js.size()>0;
		int j=-1;
		for (list<int>::iterator jt = js.begin(); jt != js.end() && b_ok; ++jt)
		{
			j = *jt;
			b_ok = (c[i][j] == 2);
		}
		if (b_ok)
		{
			twos.push_back(MatrixIndex(i, j));
			js.remove(j);
		}
		else
		{
			is2.push_back(i);
		}
	}
	is = is2;
	list<int> js2;
	for (list<int>::iterator jt = js.begin(); jt != js.end(); ++jt)
	{
		int & j = *jt;
		int i = -1;
		bool b_ok = is.size()>0;
		for (list<int>::iterator it = is.begin(); it != is.end() && b_ok; ++it)
		{
			i = *it;
			b_ok = (c[i][j] == 2);
		}
		if (b_ok)
		{
			twos.push_back(MatrixIndex(-1,j));
			is.remove(i);
		}
		else
		{
			js2.push_back(j);
		}
	}
	js = js2;
}

class info
{
public:
	list<MatrixIndex> indexpair[3];
	int maxpairs;
	int K;
	bool complete;
	info() :K(0), complete(false), maxpairs(-1)
	{
	}
	info(int _K) :info()
	{
		K = _K;
	}
	info(list<MatrixIndex> _indexpair[3], int _K) :info(_K)
	{
		init(_indexpair);
	}
	info(const info & _inf, const int _K) :info(_K)
	{
		maxpairs = _inf.maxpairs;
		complete = _inf.complete;
		init(_inf.indexpair);
	}
	void init(const list<MatrixIndex> _indexpair[3])
	{
		for (int i = 0; i < 3; ++i)
		{
			indexpair[i] = _indexpair[i];
		}
		update();
	}
	void update()
	{
		int k = K;
		maxpairs = int(indexpair[0].size());
		if (k > 0)
		{
			//1
			int ones = min(k, int(indexpair[1].size()));
			k -= ones;
			maxpairs += ones;
		}
		if (k/2 > 0)
		{
			//2
			int twos = min(k/2, int(indexpair[2].size()));
			k -= twos*2;
			maxpairs += twos;
		}
		complete = (maxpairs == int(indexpair[0].size() + indexpair[1].size() + indexpair[2].size()));
	}
};
map<string, info> g_cache;

info & travers_all(Matrix & c, list<int> & is, list<int> & js, list<MatrixIndex> indexpair[3], int K)
{
	Keys key(c, is, js);
	map<string, info>::iterator it_inf = g_cache.find(key.keys);
	if (it_inf != g_cache.end())
	{
		return it_inf->second;
	}

	info inf(K);
	bool b_one = false;
	for (list<int>::iterator it = is.begin(); it != is.end(); ++it)
	{
		int & i = *it;
		for (list<int>::iterator jt = js.begin(); jt != js.end(); ++jt)
		{
			int & j = *jt;
			if (c[i][j] == 1)
			{
				list<int> is2(is);
				is2.remove(i);
				list<int> js2(js);
				js2.remove(j);
				indexpair[1].push_back(MatrixIndex(i, j));
				info _inf = travers_all(c, is2, js2, indexpair, K);
				//info current(_inf);
				//current.indexpair[1].push_back(MatrixIndex(i, j));
				_inf.indexpair[1].push_back(MatrixIndex(i, j));
				//for (int previ = 0; previ < 2; ++previ)
				//{
				//	for (list<MatrixIndex>::iterator prev = indexpair[previ].begin(); prev != indexpair[previ].end(); prev++)
				//	{
				//		current.indexpair[previ].push_back(*prev);
				//	}
				//}
				//current.update();
				if (b_one)
				{
					//update
					if (_inf.indexpair[1].size() > inf.indexpair[1].size())
					{
						inf = _inf;
					}
					//if (current.maxpairs > inf.maxpairs)
					//{
					//	inf = _inf;
					//}

				}
				else
				{
					b_one = true;
					inf = _inf;
				}
				indexpair[1].pop_back();
				if (inf.complete)
				{
				//	break;
				}
			}
		}
		if (inf.complete)
		{
			//break;
		}
	}
	if (b_one == false)
	{
		list<MatrixIndex> ip[3];
		//for (int i = 0; i < 3; ++i)
		//{
		//	ip[i] = indexpair[i];
		//}
		///one ???????????£???
		normalize_two(c, is, js, ip[2]);
		inf = info(ip, K);
		//static info sinfo;
		//sinfo = inf;
		//return sinfo;
	}
	/// all complete
	g_cache[key.keys] = inf;
	return g_cache[key.keys];
}

info & travers_select_zero(Matrix & c, list<int> & is, list<int> & js, list<MatrixIndex> indexpair[3], int K)
{
	Keys key(c, is, js);
	map<string, info>::iterator it_inf = g_cache.find(key.keys);
	if (it_inf != g_cache.end())
	{
		return it_inf->second;
	}
	info inf(K);
	bool b_zero = false;
	for (list<int>::iterator it = is.begin(); it != is.end(); ++it)
	{
		int & i = *it;
		for (list<int>::iterator jt = js.begin(); jt != js.end(); ++jt)
		{
			int & j = *jt;
			if (c[i][j] == 0)
			{
				list<int> is2(is);
				is2.remove(i);
				list<int> js2(js);
				js2.remove(j);
				indexpair[0].push_back(MatrixIndex(i, j));
				info _inf = travers_select_zero(c, is2, js2, indexpair, K);
				info total(_inf);
				for (list<MatrixIndex>::iterator prev = indexpair[0].begin(); prev != indexpair[0].end(); prev++)
				{
					total.indexpair[0].push_back(*prev);
				}
				total.update();
				_inf.indexpair[0].push_back(MatrixIndex(i, j));
				if (b_zero)
				{
					//update
					if (total.maxpairs > inf.maxpairs)
					{
						inf = _inf;
						inf.maxpairs = total.maxpairs;
						inf.complete = total.complete;
					}
				}
				else
				{
					b_zero = true;
					inf = _inf;
					inf.maxpairs = total.maxpairs;
					inf.complete = total.complete;
				}
				indexpair[0].pop_back();
			}
			if (inf.complete)
			{
				break;
			}
		}
		if (inf.complete)
		{
			break;
		}
	}
	if (b_zero == false)
	{
		///zero ???????????£???
		inf = travers_all(c, is, js, indexpair, K);
		inf.update();
	}
	/// all complete
	g_cache[key.keys] = inf;
	return g_cache[key.keys];
}

info & search_maxpair(Matrix & c, list<int> & is, list<int> & js, int K)
{
	list<MatrixIndex> indexpair[3];
	info & inf = travers_select_zero(c, is, js, indexpair, K);
	return inf;
}
int main(){

	std::istream & c_in = cin;

	int A, B, K;
	c_in >> A >> B >> K;
	Matrix a(A, B);
	for (size_t i = 0; i < a.size(); ++i)
	{
		vector<char> & t = a[i];
		for (size_t j = 0; j < t.size(); ++j)
		{
			c_in >> t[j];
			t[j] -= '0';
		}
	}
	Matrix b(B, A);
	for (size_t i = 0; i < b.size(); ++i)
	{
		vector<char> & t = b[i];
		for (size_t j = 0; j < t.size(); ++j)
		{
			c_in >> t[j];
			t[j] -= '0';
		}
	}

	Matrix c(A, B);
	for (size_t i = 0; i < c.size(); ++i)
	{
		for (size_t j = 0; j < c[i].size(); ++j)
		{
			c[i][j] = a[i][j] + b[j][i];
		}
	}
	list<int>is;
	list<int>js;
	for (int i = 0; i < A; ++i)
	{
		is.push_back(i);
	}
	for (int j = 0; j < B; ++j)
	{
		js.push_back(j);
	}


	info inf = search_maxpair(c, is, js, K);
	cout << inf.maxpairs << endl;
}
accuracy: 1
time_ms: 30
memory_kb: 7852
final_rank: 17

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

using namespace std;

struct CWW{
    CWW(){
	ios::sync_with_stdio(false);cin.tie(0);
    }
}cww;





int A,B,K;
#define ARAI(x) (x)
#define arai(x) (A+x)
#define S (A+B)
#define G (S+1)

struct edge{
    int flow,to,rev,cost;
};
typedef vector<edge> E;
typedef vector<E> Graph;

void addedge(Graph &g,int from,int to,int f,int cost){
    int n=g[from].size();
    int m=g[to].size();
    g[from].push_back(edge{f,to,m,cost});
    g[to].push_back(edge{0,from,n,-cost});
}

namespace _ssc{
    #define SZ 500
    int h[SZ];
    int d[SZ];
    int pV[SZ];
    int pE[SZ];
};
struct ssc{
    int *h,*d,*pV,*pE;
    ssc(int V):h(_ssc::h),d(_ssc::d),pV(_ssc::pV),pE(_ssc::pE){
	fill(h,h+V,0);
    }	  
};
const int INF=114514;
int min_cost_flow(int s,int t,int f,Graph &g,ssc& info){
    using P=tuple<int,int>;

    const int V=g.size();
    int res=0;
    while(f>0){
	priority_queue<P> que;
	fill(info.d,info.d+V,INF);
	info.d[s]=0;
	que.push(P(0,s));
	while(que.size()){
	    auto p=que.top();que.pop();
	    int cost,v;tie(cost,v)=p;cost=-cost;
	    if(info.d[v]<cost)continue;
	    for(int i=0,sz=g[v].size();i<sz;i++){
		auto &e=g[v][i];
		if(e.flow>0&&info.d[e.to]>info.d[v]+e.cost+info.h[v]-info.h[e.to]){
		    info.d[e.to]=info.d[v]+e.cost+info.h[v]-info.h[e.to];
		    info.pV[e.to]=v;
		    info.pE[e.to]=i;
		    que.push(P(-info.d[e.to],e.to));
		}
	    }
	}
	if(info.d[t]==INF)return -1;
	
	for(int v=0;v<V;v++)info.h[v]+=info.d[v];
	int d=f;
	for(int v=t;v!=s;v=info.pV[v])
	    d=min(d,g[info.pV[v]][info.pE[v]].flow);
	f-=d;
	res+=d*info.h[t];
	for(int v=t;v!=s;v=info.pV[v]){
	    auto &e=g[info.pV[v]][info.pE[v]];
	    e.flow-=d;
	    g[v][e.rev].flow+=d;
	}
    }
    return res;
}
int main(){
    cin>>A>>B>>K;
    int V=A+B+2;
    Graph g(V);
    ssc info(V);
    for(int i=0;i<A;i++)addedge(g,S,ARAI(i),1,0);
    for(int i=0;i<B;i++)addedge(g,arai(i),G,1,0);
    vector<vector<int>> R(A,vector<int>(B,0));
    for(int i=0;i<A;i++){
	string s;
	cin>>s;
	for(int j=0;j<B;j++)if(s[j]=='1')R[i][j]++;			       
    }
    for(int i=0;i<B;i++){
	string s;
	cin>>s;
	for(int j=0;j<A;j++)if(s[j]=='1')R[j][i]++;			       
    }
    for(int i=0;i<A;i++)
	for(int j=0;j<B;j++)
	    addedge(g,ARAI(i),arai(j),1,R[i][j]);
    int res=0,cost,allcost=0;
    while((cost=min_cost_flow(S,G,1,g,info))!=-1){
	allcost+=cost;
	if(allcost<=K)res++;
	else break;
    }
    cout<<res<<endl;
}
accuracy: 1
time_ms: 40
memory_kb: 4808
final_rank: 3