Problem:
G: Dungeon of Cards / カードの迷宮
物語
ここは不思議の国あじふらい．あじふらい辺境の地に位置するカードの迷宮には，金銀財宝が眠ると伝えられている．好奇心旺盛なあいずにゃんは，この言い伝えを聞くやいなや，友人のウィを連れてカードの迷宮を目指す旅に出ることにした．
翌日，旅の計画を立てるためにあいずにゃんがウィの家を訪れると，ウィは何やら考え込んでいるようだった．どうやら用意周到なウィはカードの迷宮に関する重要な情報を入手したようだ．それは，カードの迷宮には
N
枚の扉があり，それぞれの扉を開けるためにカードが必要になるということだ．
カードの迷宮への道中には，扉を開くためのカードを扱う店がある．ウィはここでカードを調達しようと考えているらしいが，問題なのは予算である．あいずにゃんとウィは決してお金持ちではないので，カードにお金をかけすぎてしまうと道中の食料を十分に確保できない可能性があるのだ．
幸い
N
枚の扉の情報は，これまで迷宮に挑んだ人々の記録から知ることができた．これなら効率の良いカードの買い方を計算できるかもしれない．しかし，２人で考えるには少し難しい．そこであいずにゃんとウィは，あじふらいに住む優秀なプログラマであるあなたに依頼をすることにした．
問題
N
枚の扉と
M
枚のカードがある．扉・カードともに１枚につき英大文字アルファベット ('A'-'Z') 1つと1桁の数字 ('0'-'9') が描かれている．扉にカードをかざすと，カードに描かれたアルファベット，もしくは数字のどちらか一方でも扉のものと一致していれば，その扉を開けることができる．このときカードはなくならないため，同じカードを何度でも使いまわすことができる．また，カードにはそれぞれ値段が付いている．
N
枚の扉と
M
枚のカードの情報を元に，すべての扉を開けることができるカードの買い方のうち，要する金額が最小となる場合の金額を計算するプログラムを作成せよ．
入力形式
入力は以下の形式からなる．
N
a_1
b_1
...
a_N
b_N
M
c_1
d_1
e_1
...
c_M
d_M
e_M
1行目では扉の枚数を表す整数
N
が与えられる．続く
N
行のうち，
i
行目では
i
番目の扉に書かれた英大文字アルファベット
a_i
と1桁の数字
b_i
が与えられる．
続く1行では，店で扱われているカードの枚数
M
が与えられる．続く
M
行のうち，
j
行目では
j
番目のカードに書かれた英大文字アルファベット
c_j
と1桁の数字
d_j
，価格
e_j
が与えられる．
入力は以下の制約を満たす．
1 ≤ N, M ≤ 10{,}000
a_i, c_j
はアルファベット大文字 ('A'-'Z') 1文字
b_i, d_j
は1桁の数字 ('0'-'9') 1文字
1 ≤ e_j ≤ 1{,}000
N, M, e_j
はすべて整数
出力形式
迷宮の扉をすべて開けるために必要なカードを揃えるための最小予算を1行に出力せよ．どのようにカードを買っても全ての扉を開けられない場合，-1を1行に出力せよ．
入力例１
4
D 1
D 2
A 3
D 4
4
A 1 7
D 4 5
D 3 6
B 3 3
出力例１
6
入力例2
4
D 1
D 2
A 3
D 4
4
A 1 7
D 4 5
D 3 10
B 3 3
出力例2
8
入力例3
5
D 1
D 2
A 3
Z 0
D 4
4
A 1 7
D 4 5
D 3 6
B 3 3
出力例3
-1

Submitted solutions:

code_snippet: // AOJ #2675 Dungeon of Cards
// 2025.2.16

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const ll INF = 1e15;
 
ll letterCost[26];
ll digitCost[10];
ll costPair[26][10];
 
struct Door { int l, d; };
 
int doorMask[26];
bool letterInDoor[26], digitInDoor[10];
 
ll hungarian_max(const vector<vector<ll>> &mat, int nRows, int nCols) {
    int n = max(nRows, nCols);
    vector<vector<ll>> a(n, vector<ll>(n, 0));
    for (int i = 0; i < n; i++){
        for (int j = 0; j < n; j++){
            if(i < nRows && j < nCols) a[i][j] = mat[i][j];
            else a[i][j] = 0;
        }
    }
    vector<ll> u(n+1, 0), v(n+1, 0);
    vector<int> p(n+1, 0), way(n+1, 0);
    for (int i = 1; i <= n; i++) {
        p[0] = i;
        vector<ll> minv(n+1, INF);
        vector<char> used(n+1, false);
        int j0 = 0;
        do {
            used[j0] = true;
            int i0 = p[j0], j1 = 0;
            ll delta = INF;
            for (int j = 1; j <= n; j++) {
                if (!used[j]) {
                    ll cur = -a[i0-1][j-1] - u[i0] - v[j];
                    if(cur < minv[j]){
                        minv[j] = cur;
                        way[j] = j0;
                    }
                    if(minv[j] < delta){
                        delta = minv[j];
                        j1 = j;
                    }
                }
            }
            for (int j = 0; j <= n; j++){
                if(used[j]){
                    u[p[j]] += delta;
                    v[j] -= delta;
                } else minv[j] -= delta;
            }
            j0 = j1;
        } while(p[j0] != 0);
        do {
            int j1 = way[j0];
            p[j0] = p[j1];
            j0 = j1;
        } while(j0);
    }
    ll res = 0;
    for (int j = 1; j <= n; j++) res += a[p[j]-1][j-1];
    return res;
}
 
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    int N;
    cin >> N;
    vector<Door> doors;
    for (int i = 0; i < 26; i++){
        letterInDoor[i] = false;
        doorMask[i] = 0;
    }
    for (int i = 0; i < 10; i++) digitInDoor[i] = false;
 
    for (int i = 0; i < N; i++){
        char lc, dc;
        cin >> lc >> dc;
        int l = lc - 'A';
        int d = dc - '0';
        doors.push_back({l,d});
        letterInDoor[l] = true;
        digitInDoor[d] = true;
    }
 
    int M;
    cin >> M;
    for (int i = 0; i < 26; i++) letterCost[i] = INF;
    for (int i = 0; i < 10; i++) digitCost[i] = INF;
    for (int i = 0; i < 26; i++){
        for (int j = 0; j < 10; j++) costPair[i][j] = INF;
    }
 
    for (int i = 0; i < M; i++){
        char lc, dc;
        ll price;
        cin >> lc >> dc >> price;
        int l = lc - 'A';
        int d = dc - '0';
        letterCost[l] = min(letterCost[l], price);
        digitCost[d] = min(digitCost[d], price);
        costPair[l][d] = min(costPair[l][d], price);
    }
 
    for(auto &dr : doors){
        if(letterCost[dr.l]==INF && digitCost[dr.d]==INF){
            cout << -1 << endl;
            return 0;
        }
    }
 
    vector<int> lettersList, digitsList;
    for(auto &dr : doors) doorMask[dr.l] |= (1 << dr.d);
    for (int i = 0; i < 26; i++){
        if(letterInDoor[i]) lettersList.push_back(i);
    }
    for (int i = 0; i < 10; i++){
        if(digitInDoor[i]) digitsList.push_back(i);
    }
 
    int k = digitsList.size();
    ll bestAns = INF;
    for (int mask = 0; mask < (1 << k); mask++){
        vector<int> chosenDigits;
        ll sumDigits = 0;
        for (int j = 0; j < k; j++){
            if(mask & (1 << j)){
                int d = digitsList[j];
                chosenDigits.push_back(d);
                sumDigits += digitCost[d];
            }
        }
 
        vector<int> forced, optional;
        for (int l : lettersList){
            bool isForced = false;
            for (int d = 0; d < 10; d++){
                if(doorMask[l] & (1 << d)){
                    bool inY = false;
                    for (int cd : chosenDigits){
                        if(cd == d){ inY = true; break; }
                    }
                    if(!inY){
                        isForced = true;
                        break;
                    }
                }
            }
            if(isForced) forced.push_back(l);
            else optional.push_back(l);
        }
 
        int nLeft = forced.size() + optional.size();
        int nRight = chosenDigits.size();
 
        vector<vector<ll>> mat(nLeft, vector<ll>(nRight, 0));
        for (int i = 0; i < (int)forced.size(); i++){
            int l = forced[i];
            for (int j = 0; j < nRight; j++){
                int d = chosenDigits[j];
                ll w = 0;
                if(costPair[l][d] < INF)
                    w = max(0LL, letterCost[l] + digitCost[d] - costPair[l][d]);
                mat[i][j] = w;
            }
        }
        for (int i = 0; i < (int)optional.size(); i++){
            int l = optional[i];
            for (int j = 0; j < nRight; j++){
                int d = chosenDigits[j];
                ll w = 0;
                if(costPair[l][d] < INF) w = max(0LL, digitCost[d] - costPair[l][d]);
                mat[forced.size()+i][j] = w;
            }
        }
 
        ll D = 0;
        if(nRight > 0) D = hungarian_max(mat, nLeft, nRight);
 
        ll sumForced = 0;
        for (int l : forced) sumForced += letterCost[l];
 
        ll candidate = sumDigits + sumForced - D;
        bestAns = min(bestAns, candidate);
    }
    if(bestAns >= INF) cout << -1 << endl;
    else cout << bestAns << endl;
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3596
final_rank: 5

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

#include <algorithm>
#include <cassert>
#include <limits>
#include <queue>
#include <vector>

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())});
        int from_id = int(g[from].size());
        int to_id = int(g[to].size());
        if (from == to) to_id++;
        g[from].push_back(_edge{to, to_id, cap, cost});
        g[to].push_back(_edge{from, from_id, 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_per_flow = -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_per_flow == d) {
                result.pop_back();
            }
            result.push_back({flow, cost});
            prev_cost_per_flow = d;
        }
        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;
};

}  // namespace atcoder

using namespace std;
using namespace atcoder;
typedef long long ll;

int main(){
	int n; cin >> n;
	vector<vector<int>> door(10, vector<int>(26));
	vector<vector<ll>> key(10, vector<ll>(26, -1));
	for (int i=0; i<n; i++){
		char c; int x; cin >> c >> x;
		door[x][c - 'A'] = 1;
	}
	int m; cin >> m;
	for (int i=0; i<m; i++){
		char c; int x, e; cin >> c >> x >> e;
		if (key[x][c - 'A'] == -1 || key[x][c - 'A'] > e){
			key[x][c - 'A'] = e;
		}
	}
	const ll INF = 1e9;
	ll ans = 1e9;
	for (int num=0; num<1<<10; num++){
		mcf_graph<int,ll> mcf(38);
		for (int j=0; j<10; j++){
			if (num>>j&1){
				mcf.add_edge(36, j, 1, 0);
			}
			mcf.add_edge(36, j, 1000, INF);
		}
		vector<bool> hvs(26);
		for (int i=0; i<10; i++){
			for (int j=0; j<26; j++){
				if ((num>>i&1)==0 && door[i][j]==1){
					hvs[j] = true;
				}
			}
		}
		for (int j=0; j<26; j++){
			if (hvs[j]){
				mcf.add_edge(10+j, 37, 1, 0);
			}
			mcf.add_edge(10+j, 37, 1000, INF);
		}
		vector<bool> ok(26);
		bool mode = true;
		for (int i=0; i<10; i++){
			if ((num>>i&1)==0) continue;
			bool havnum = false;
			for (int j=0; j<26; j++){
				if (key[i][j] != -1){
					ok[j] = true;
					havnum = true;
					mcf.add_edge(i, 10+j, 1, key[i][j]);
				}
			}
			if (!havnum){
				mode = false;
				break;
			}
		}
		for (int j=0; j<26; j++){
			if (hvs[j] && !ok[j]){
				mode = false;
				break;
			}
		}
		if (!mode) continue;
		mcf.add_edge(36, 37, 1000, INF*2);
		ans = min(ans, mcf.flow(36, 37, 260).second % INF);
	}
	if (ans == INF){
		cout << -1 << endl;
	}else{
		cout << ans << endl;
	}
	
}
accuracy: 1
time_ms: 60
memory_kb: 3508
final_rank: 6

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 (int 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 N;
	cin>>N;
	vector<int> p(N),q(N);
	rep(i,N){
		char a,b;
		cin>>a>>b;
		p[i]=a-'A';
		q[i]=b-'0';
	}
	int M;
	cin>>M;
	vector<int> A(M),B(M),C(M),S(26,INF),T(10,INF);
	vector<vector<int>> table(26,vector<int>(10,INF));
	int tmp=0;
	rep(i,M){
		char a,b;
		cin>>a>>b>>C[i];
		A[i]=a-'A';
		B[i]=b-'0';
		tmp=(tmp|(1<<B[i]));
		chmin(S[A[i]],C[i]);
		chmin(T[B[i]],C[i]);
		chmin(table[A[i]][B[i]],C[i]);
	}
	rep(i,N){
		if(S[p[i]]==INF&&T[q[i]]==INF){
			cout<<"-1\n";
			return;
		}
	}
	int X=1e3;
	int ans=INF;
	rep(use,1024){
		if((tmp&use)!=use) continue;
		set<int> s;
		rep(i,N){
			if((use&(1<<q[i]))==0){
				s.insert(p[i]);
			}
		}
		int J=0;
		rep(j,26){
			if(s.count(j)&&S[j]==INF) J=1;
		}
		rep(j,10){
			if(0!=(use&(1<<j))&&T[j]==INF) J=1;
		}
		if(J) continue;
		mcf_graph<int,int> G(10+26+2);
		G.add_edge(36,37,100,X);
		rep(i,26) rep(j,10){
			if(table[i][j]==INF) continue;
			if(((1<<j)&use)==0||!s.count(i)) continue;
			int tmp=S[i]+T[j]-table[i][j];
			if(tmp<0) continue;
			G.add_edge(i,j+26,1,X-tmp);
		}
		int base=0;
		rep(j,26) if(s.count(j)) base+=S[j];
		rep(i,10) if(use&(1<<i)) base+=T[i];
		rep(i,26) G.add_edge(36,i,1,0);
		rep(i,10) G.add_edge(i+26,37,1,0);
		int a=G.flow(36,37,100).second;
		base+=a-100*X;
		chmin(ans,base);
	}
	cout<<ans<<"\n";
}
accuracy: 1
time_ms: 150
memory_kb: 3668
final_rank: 9

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001


#define MAX 26
#define SIZE 10005

struct Info{

	int x;
	char ch;
};

struct Card{

	int x;
	ll price;
	char ch;
};

struct DATA{
	DATA(int arg_num,ll arg_price){
		num = arg_num;
		price = arg_price;
	}
	int num;
	ll price;
};

int POW[MAX+1];
int table[10];
ll dp[MAX+1][1024],MINI[10];
bool check[10],need[26];
vector<int> V[26],OTHER;
vector<DATA> D[26];

Info info[SIZE];
Card card[SIZE];

int main(){

	POW[0] = 1;
	for(int i = 1; i <= MAX; i++){

		POW[i] = POW[i-1]*2;
	}

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

	char buf[2];

	for(int i = 0; i < N; i++){

		scanf("%s %d",buf,&info[i].x);
		info[i].ch = buf[0];
	}

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

	for(int i = 0; i < M; i++){

		scanf("%s %d %lld",buf,&card[i].x,&card[i].price);
		card[i].ch = buf[0];

		table[card[i].x]++;
	}

	ll ans = HUGE_NUM;

	for(int state = 0; state < POW[10]; state++){

		for(int loop = 0; loop <= 9; loop++){
			if(state&POW[loop]){

				check[loop] = true;
			}else{

				check[loop] = false;
			}
		}

		for(int i = 0; i < 26; i++){

			need[i] = false;
		}

		//扉を走査
		for(int i = 0; i < N; i++){
			if(!check[info[i].x]||table[info[i].x] == 0){

				need[info[i].ch-'A'] = true; //必要な色
			}
		}

		for(int i = 0; i < 26; i++){

			V[i].clear();
			D[i].clear();
		}
		OTHER.clear();

		map<int,int> MAP;
		int num_need = 0;

		for(int i = 0; i < 26; i++){
			if(need[i]){

				MAP[i] = num_need++;
			}
		}

		//カードを仕分ける
		for(int i = 0; i < M; i++){
			if(check[card[i].x]){
				if(need[card[i].ch-'A']){ //必要な色

					int ind = MAP[card[i].ch-'A'];
					V[ind].push_back(i);

				}else{

					OTHER.push_back(i);
				}
			}
		}

		for(int i = 0; i < num_need; i++){
			for(int k = 0; k <= 9; k++){

				MINI[k] = HUGE_NUM;
			}
			for(int a = 0; a < V[i].size(); a++){

				int num = card[V[i][a]].x;
				ll p = card[V[i][a]].price;

				MINI[num] = min(MINI[num],p);
			}

			for(int k = 0; k <= 9; k++){
				if(MINI[k] == HUGE_NUM)continue;

				D[i].push_back(DATA(k,MINI[k]));
			}
		}

		for(int i = 0; i <= num_need; i++){
			for(int s = 0; s <= state; s++){

				dp[i][s] = HUGE_NUM;
			}
		}

		dp[0][0] = 0; //dp[必要色のカバー数][数字の集合] := 最小コスト

		for(int i = 0; i < OTHER.size(); i++){
			for(int s = state; s >= 0; s--){
				if(dp[0][s] == HUGE_NUM)continue;

				int tmp = card[OTHER[i]].x;
				ll add = card[OTHER[i]].price;

				dp[0][s|POW[tmp]] = min(dp[0][s|POW[tmp]],dp[0][s]+add);
			}
		}

		for(int i = 0; i < num_need; i++){

			for(int k = 0; k < D[i].size(); k++){
				//1つだけ追加
				for(int s = state; s >= 0; s--){
					if(dp[i][s] == HUGE_NUM)continue;

					int tmp = D[i][k].num;
					ll add = D[i][k].price;

					dp[i+1][s|POW[tmp]] = min(dp[i+1][s|POW[tmp]],dp[i][s]+add);
				}
				//複数追加
				for(int s = state; s >= 0; s--){
					if(dp[i+1][s] == HUGE_NUM)continue;

					int tmp = D[i][k].num;
					ll add = D[i][k].price;

					dp[i+1][s|POW[tmp]] = min(dp[i+1][s|POW[tmp]],dp[i+1][s]+add);
				}
			}
		}
		ans = min(ans,dp[num_need][state]);
	}

	if(ans == HUGE_NUM){

		printf("-1\n");

	}else{

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 330
memory_kb: 3928
final_rank: 12

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001


#define MAX 26
#define SIZE 10005

struct Info{

	int x;
	char ch;
};

struct Card{

	int x;
	ll price;
	char ch;
};

struct DATA{
	DATA(int arg_num,ll arg_price){
		num = arg_num;
		price = arg_price;
	}
	int num;
	ll price;
};

int POW[MAX+1];
int table[10];
ll dp[MAX+1][1024],MINI[10];
bool check[10],need[26];
vector<int> V[26],OTHER;
vector<DATA> D[26];

Info info[SIZE];
Card card[SIZE];

int main(){

	POW[0] = 1;
	for(int i = 1; i <= MAX; i++){

		POW[i] = POW[i-1]*2;
	}

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

	char buf[2];

	for(int i = 0; i < N; i++){

		scanf("%s %d",buf,&info[i].x);
		info[i].ch = buf[0];
	}

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

	for(int i = 0; i < M; i++){

		scanf("%s %d %lld",buf,&card[i].x,&card[i].price);
		card[i].ch = buf[0];

		table[card[i].x]++;
	}

	ll ans = HUGE_NUM;

	for(int state = 0; state < POW[10]; state++){

		for(int loop = 0; loop <= 9; loop++){
			if(state&POW[loop]){

				check[loop] = true;
			}else{

				check[loop] = false;
			}
		}

		for(int i = 0; i < 26; i++){

			need[i] = false;
		}

		//扉を走査
		for(int i = 0; i < N; i++){
			if(!check[info[i].x]||table[info[i].x] == 0){

				//printf("色%cが必要\n",info[i].ch);
				need[info[i].ch-'A'] = true; //必要な色
			}
		}

		for(int i = 0; i < 26; i++){

			V[i].clear();
			D[i].clear();
		}
		OTHER.clear();

		map<int,int> MAP;
		int num_need = 0;

		for(int i = 0; i < 26; i++){
			if(need[i]){

				MAP[i] = num_need++;
			}
		}

		//printf("num_need:%d\n",num_need);


		//カードを仕分ける
		for(int i = 0; i < M; i++){
			if(check[card[i].x]){
				if(need[card[i].ch-'A']){ //必要な色

					int ind = MAP[card[i].ch-'A'];
					V[ind].push_back(i);
					//printf("カード%dを%dにpush\n",i,ind);

				}else{

					//printf("カード%dをotherにpush\n",i);
					OTHER.push_back(i);
				}
			}
		}

		for(int i = 0; i < num_need; i++){
			for(int k = 0; k <= 9; k++){

				MINI[k] = HUGE_NUM;
			}
			for(int a = 0; a < V[i].size(); a++){

				int num = card[V[i][a]].x;
				ll p = card[V[i][a]].price;

				MINI[num] = min(MINI[num],p);
			}

			for(int k = 0; k <= 9; k++){
				if(MINI[k] == HUGE_NUM)continue;

				D[i].push_back(DATA(k,MINI[k]));
			}
		}

		for(int i = 0; i <= num_need; i++){
			for(int s = 0; s <= state; s++){

				dp[i][s] = HUGE_NUM;
			}
		}

		dp[0][0] = 0; //dp[必要色のカバー数][数字の集合] := 最小コスト

		for(int i = 0; i < OTHER.size(); i++){
			for(int s = state; s >= 0; s--){
				if(dp[0][s] == HUGE_NUM)continue;

				int tmp = card[OTHER[i]].x;
				ll add = card[OTHER[i]].price;

				dp[0][s|POW[tmp]] = min(dp[0][s|POW[tmp]],dp[0][s]+add);
			}
		}

		for(int i = 0; i < num_need; i++){

			for(int k = 0; k < D[i].size(); k++){
				//1つだけ追加
				for(int s = state; s >= 0; s--){
					if(dp[i][s] == HUGE_NUM)continue;

					int tmp = D[i][k].num;
					ll add = D[i][k].price;

					dp[i+1][s|POW[tmp]] = min(dp[i+1][s|POW[tmp]],dp[i][s]+add);
					//printf("dp[%d][%d]:%lld\n",i+1,s|POW[tmp],dp[i+1][s|POW[tmp]]);
				}
				//複数追加
				for(int s = state; s >= 0; s--){
					if(dp[i+1][s] == HUGE_NUM)continue;

					int tmp = D[i][k].num;
					ll add = D[i][k].price;

					dp[i+1][s|POW[tmp]] = min(dp[i+1][s|POW[tmp]],dp[i+1][s]+add);
					//printf("dp[%d][%d]:%lld\n",i+1,s|POW[tmp],dp[i+1][s|POW[tmp]]);
				}
			}
		}
		ans = min(ans,dp[num_need][state]);
	}

	if(ans == HUGE_NUM){

		printf("-1\n");

	}else{

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 330
memory_kb: 3912
final_rank: 11

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001


#define MAX 26
#define SIZE 10005

struct Info{

	int x;
	char ch;
};

struct Card{

	int x;
	ll price;
	char ch;
};

int POW[MAX+1];
int table[10];
ll dp[MAX+1][1024],COST[MAX+1][1024];
bool check[10],need[26];
vector<int> V[26],OTHER;

Info info[SIZE];
Card card[SIZE];

int main(){

	POW[0] = 1;
	for(int i = 1; i <= MAX; i++){

		POW[i] = POW[i-1]*2;
	}

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

	char buf[2];

	for(int i = 0; i < N; i++){

		scanf("%s %d",buf,&info[i].x);
		info[i].ch = buf[0];
	}

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

	for(int i = 0; i < M; i++){

		scanf("%s %d %lld",buf,&card[i].x,&card[i].price);
		card[i].ch = buf[0];

		table[card[i].x]++;
	}

	ll ans = HUGE_NUM;

	for(int state = 0; state < POW[10]; state++){

		for(int loop = 0; loop <= 9; loop++){
			if(state&POW[loop]){

				check[loop] = true;
			}else{

				check[loop] = false;
			}
		}

		for(int i = 0; i < 26; i++){

			need[i] = false;
		}

		//扉を走査
		for(int i = 0; i < N; i++){
			if(!check[info[i].x]||table[info[i].x] == 0){

				//printf("色%cが必要\n",info[i].ch);
				need[info[i].ch-'A'] = true; //必要な色
			}
		}

		for(int i = 0; i < 26; i++){

			V[i].clear();
		}
		OTHER.clear();

		map<int,int> MAP;
		int num_need = 0;

		for(int i = 0; i < 26; i++){
			if(need[i]){

				MAP[i] = num_need++;
			}
		}

		//printf("num_need:%d\n",num_need);


		//カードを仕分ける
		for(int i = 0; i < M; i++){
			if(check[card[i].x]){
				if(need[card[i].ch-'A']){ //必要な色

					int ind = MAP[card[i].ch-'A'];
					V[ind].push_back(i);
					//printf("カード%dを%dにpush\n",i,ind);

				}else{

					//printf("カード%dをotherにpush\n",i);
					OTHER.push_back(i);
				}
			}
		}

		for(int i = 0; i <= num_need; i++){
			for(int s = 0; s <= state; s++){

				dp[i][s] = HUGE_NUM;
			}
		}

		dp[0][0] = 0; //dp[必要色のカバー数][数字の集合] := 最小コスト

		for(int i = 0; i < OTHER.size(); i++){
			for(int s = state; s >= 0; s--){
				if(dp[0][s] == HUGE_NUM)continue;

				int tmp = card[OTHER[i]].x;
				ll add = card[OTHER[i]].price;

				dp[0][s|POW[tmp]] = min(dp[0][s|POW[tmp]],dp[0][s]+add);
			}
		}

		for(int i = 0; i < num_need; i++){

			for(int k = 0; k < V[i].size(); k++){
				//1つだけ追加
				for(int s = state; s >= 0; s--){
					if(dp[i][s] == HUGE_NUM)continue;

					int tmp = card[V[i][k]].x;
					ll add = card[V[i][k]].price;

					dp[i+1][s|POW[tmp]] = min(dp[i+1][s|POW[tmp]],dp[i][s]+add);
					//printf("dp[%d][%d]:%lld\n",i+1,s|POW[tmp],dp[i+1][s|POW[tmp]]);
				}
				//複数追加
				for(int s = state; s >= 0; s--){
					if(dp[i+1][s] == HUGE_NUM)continue;

					int tmp = card[V[i][k]].x;
					ll add = card[V[i][k]].price;

					dp[i+1][s|POW[tmp]] = min(dp[i+1][s|POW[tmp]],dp[i+1][s]+add);
					//printf("dp[%d][%d]:%lld\n",i+1,s|POW[tmp],dp[i+1][s|POW[tmp]]);
				}
			}
		}
		ans = min(ans,dp[num_need][state]);
	}

	if(ans == HUGE_NUM){

		printf("-1\n");

	}else{

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 4840
memory_kb: 3924
final_rank: 15

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001


#define MAX 26
#define SIZE 10005

struct Info{

	int x;
	char ch;
};

struct Card{

	int x;
	ll price;
	char ch;
};

int POW[MAX+1];
ll dp[MAX+1][1024];
bool check[10],need[26];
vector<int> V[26],OTHER;

Info info[SIZE];
Card card[SIZE];

int main(){

	POW[0] = 1;
	for(int i = 1; i <= MAX; i++){

		POW[i] = POW[i-1]*2;
	}

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

	char buf[2];

	for(int i = 0; i < N; i++){

		scanf("%s %d",buf,&info[i].x);
		info[i].ch = buf[0];
	}

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

	for(int i = 0; i < M; i++){

		scanf("%s %d %lld",buf,&card[i].x,&card[i].price);
		card[i].ch = buf[0];
	}

	ll ans = HUGE_NUM;

	for(int state = 0; state < POW[10]; state++){

		for(int loop = 0; loop <= 9; loop++){
			if(state&POW[loop]){

				check[loop] = true;
			}else{

				check[loop] = false;
			}
		}

		for(int i = 0; i < 26; i++){

			need[i] = false;
		}

		//扉を走査
		for(int i = 0; i < N; i++){
			if(!check[info[i].x]){

				need[info[i].ch-'A'] = true; //必要な色
			}
		}

		for(int i = 0; i < 26; i++){

			V[i].clear();
		}
		OTHER.clear();

		map<int,int> MAP;
		int num_need = 0;

		for(int i = 0; i < 26; i++){
			if(need[i]){

				MAP[i] = num_need++;
			}
		}


		//カードを仕分ける
		for(int i = 0; i < M; i++){
			if(check[card[i].x]){
				if(need[card[i].ch-'A']){ //必要な色

					int ind = MAP[card[i].ch-'A'];
					V[ind].push_back(i);

				}else{

					OTHER.push_back(i);
				}
			}
		}

		for(int i = 0; i <= num_need; i++){
			for(int s = 0; s <= state; s++){

				dp[i][s] = HUGE_NUM;
			}
		}

		dp[0][0] = 0; //dp[必要色のカバー数][数字の集合] := 最小コスト

		for(int i = 0; i < OTHER.size(); i++){
			for(int s = state; s >= 0; s--){
				if(dp[0][s] == HUGE_NUM)continue;

				int tmp = card[OTHER[i]].x;
				ll add = card[OTHER[i]].price;

				dp[0][s|POW[tmp]] = min(dp[0][s|POW[tmp]],dp[0][s]+add);
			}
		}

		for(int i = 0; i < num_need; i++){
			for(int k = 0; k < V[i].size(); k++){
				for(int s = 0; s <= state; s++){
					if(dp[i][s] == HUGE_NUM)continue;

					int tmp = card[V[i][k]].x;
					ll add = card[V[i][k]].price;

					dp[i+1][s|POW[tmp]] = min(dp[i+1][s|POW[tmp]],dp[i][s]+add);
				}
			}
		}

		ans = min(ans,dp[num_need][state]);
	}

	if(ans == HUGE_NUM){

		printf("-1\n");

	}else{

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 0.9838709677419355
time_ms: 2500
memory_kb: 3928
final_rank: 17

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001


#define MAX 26
#define SIZE 10005

struct Info{

	int x;
	char ch;
};

struct Card{

	int x;
	ll price;
	char ch;
};

int POW[MAX+1];
ll dp[MAX+1][1024];
bool check[10],need[26];
vector<int> V[26],OTHER;

Info info[SIZE];
Card card[SIZE];

int main(){

	POW[0] = 1;
	for(int i = 1; i <= MAX; i++){

		POW[i] = POW[i-1]*2;
	}

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

	char buf[2];

	for(int i = 0; i < N; i++){

		scanf("%s %d",buf,&info[i].x);
		info[i].ch = buf[0];
	}

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

	for(int i = 0; i < M; i++){

		scanf("%s %d %lld",buf,&card[i].x,&card[i].price);
		card[i].ch = buf[0];
	}

	ll ans = HUGE_NUM;

	for(int state = 0; state < POW[10]; state++){

		for(int loop = 0; loop <= 9; loop++){
			if(state&POW[loop]){

				check[loop] = true;
			}else{

				check[loop] = false;
			}
		}

		for(int i = 0; i < 26; i++){

			need[i] = false;
		}

		//扉を走査
		for(int i = 0; i < N; i++){
			if(!check[info[i].x]){

				need[info[i].ch-'A'] = true; //必要な色
			}
		}

		for(int i = 0; i < 26; i++){

			V[i].clear();
		}
		OTHER.clear();

		map<int,int> MAP;
		int num_need = 0;

		for(int i = 0; i < 26; i++){
			if(need[i]){

				MAP[i] = num_need++;
			}
		}

		//カードを仕分ける
		for(int i = 0; i < M; i++){
			if(check[card[i].x]){
				if(need[card[i].ch-'A']){ //必要な色

					int ind = MAP[card[i].ch-'A'];
					V[ind].push_back(i);

				}else{

					OTHER.push_back(i);
				}
			}
		}

		for(int i = 0; i <= num_need; i++){
			for(int s = 0; s <= state; s++){

				dp[i][s] = HUGE_NUM;
			}
		}

		dp[0][0] = 0; //dp[必要色のカバー数][数字の集合] := 最小コスト

		for(int i = 0; i < OTHER.size(); i++){
			for(int s = state-1; s >= 0; s--){
				if(dp[0][s] == HUGE_NUM)continue;

				int tmp = card[OTHER[i]].x;
				ll add = card[OTHER[i]].price;

				dp[0][s|POW[tmp]] = min(dp[0][s|POW[tmp]],dp[0][s]+add);
			}
		}

		for(int i = 0; i < num_need; i++){
			for(int k = 0; k < V[i].size(); k++){
				for(int s = 0; s < state; s++){
					if(dp[i][s] == HUGE_NUM)continue;

					int tmp = card[V[i][k]].x;
					ll add = card[V[i][k]].price;

					dp[i+1][s|POW[tmp]] = min(dp[i+1][s|POW[tmp]],dp[i][s]+add);
				}
			}
		}

		ans = min(ans,dp[num_need][state]);
	}

	if(ans == HUGE_NUM){

		printf("-1\n");

	}else{

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 0.8709677419354839
time_ms: 2740
memory_kb: 3896
final_rank: 18

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;

ll dp[30][60000], exist[30][30], cost[30][30], three[12];

int main() {
    int N; cin >> N;
    for(int i=0; i<N; i++) {
        char u; ll v; cin >> u >> v;
        exist[u-'A'][v] = true;
    }
    
    
    int M; cin >> M;
    fill(cost[0], cost[28], LONGINF);
    for(int i=0; i<M; i++) {
        char x; ll y, z; cin >> x >> y >> z;
        chmin(cost[x-'A'][y], z);
    }

    three[0] = 1;
    for(int i=1; i<=10; i++) three[i] = three[i-1] * 3;

    fill(dp[0], dp[28], LONGINF);
    dp[0][0] = 0;
    for(int i=0; i<26; i++) {
        for(int bit=0; bit<three[10]; bit++) {
            if(dp[i][bit] == LONGINF) continue;
            for(int d=0; d<10; d++) {
                int nbit = bit - (bit%three[d+1]/three[d]*three[d]) + three[d]*2;
                chmin(dp[i][nbit], dp[i][bit] + cost[i][d]);
                chmin(dp[i+1][nbit], dp[i][bit] + cost[i][d]);
            }

            int b = bit;
            for(int d=0; d<10; d++) {
                if(!exist[i][d] or b%three[d+1]/three[d] != 0) continue;
                b += three[d];
            }

            chmin(dp[i+1][b], dp[i][bit]);
        }
    }

    ll ans = LONGINF;
    for(int bit=0; bit<three[10]; bit++) {
        bool ok = true;
        for(int d=0; d<10; d++) {
            if(bit%three[d+1]/three[d] == 1) {
                ok = false;
                break;
            }
        }

        if(ok) chmin(ans, dp[26][bit]);
    }
    if(ans == LONGINF) cout << -1 << endl;
    else cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 16240
final_rank: 14

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 = 40; // TODO:initialize
const int INF = 10000; // 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??????t????????????f???????°??????¨???(???????????????-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();
                // dbg(p);
                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 -191919;

        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);
            // dbg(v);
        }

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

const int M = 1000000;
bool door[10][26]={};
int cost[10][26];

int main()
{
    int n;
    scanf(" %d", &n);

    while(n--)
    {
        char c;
        int d;
        scanf(" %c %d", &c, &d);
        door[d][c-'A'] = true;
    }

    fill(cost[0],cost[10],M*100);
    int m;
    scanf(" %d", &m);
    while(m--)
    {
        char c;
        int d,e;
        scanf(" %c %d %d", &c, &d, &e);
        cost[d][c-'A'] = min(cost[d][c-'A'], e);
    }

    int S = 36, T = S+1;
    V = T+1;

    int ans = M;
    rep(mask,1<<10)
    {
        rep(i,V) G[i].clear();

        int lb = 0;

        // source to number
        rep(i,10)
        {
            if(mask>>i&1)
            {
                add_edge(S,i,1,-M);
                add_edge(S,i,INF-1,0);
                ++lb;
            }
            else
            {
                add_edge(S,i,INF,0);
            }
        }

        // number to alphabet
        rep(i,10)rep(j,26) add_edge(i,10+j,1,cost[i][j]);

        // alphabet to sink
        bool must[26]={};
        rep(i,26)
        {
            int amask = 0;
            rep(j,10)if(door[j][i]) amask |= 1<<j;

            rep(j,10)
            {
                if((amask>>j&1) && !(mask>>j&1)) must[i]=true;
            }
        }

        rep(i,26)
        {
            if(must[i])
            {
                add_edge(10+i,T,1,-M);
                add_edge(10+i,T,INF-1,0);
                ++lb;
            }
            else
            {
                add_edge(10+i,T,INF,0);
            }
        }

        int cur = 0;
        rep(ff,36)
        {
            int res = min_cost_flow(S,T,1);
            if(res==-191919) break;

            cur += res;
            ans = min(ans,cur+M*lb);
        }
    }

    if(ans==M) ans = -1;
    printf("%d\n", ans);
    return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 3280
final_rank: 8

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 = 40; // TODO:initialize
const int INF = 10000; // 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??????t????????????f???????°??????¨???(???????????????-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();
                // dbg(p);
                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 -191919;

        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);
            // dbg(v);
        }

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

const int M = 1000000;
bool door[10][26]={};
int cost[10][26];

int main()
{
    int n;
    scanf(" %d", &n);

    while(n--)
    {
        char c;
        int d;
        scanf(" %c %d", &c, &d);
        door[d][c-'A'] = true;
    }

    fill(cost[0],cost[10],M*100);
    int m;
    scanf(" %d", &m);
    while(m--)
    {
        char c;
        int d,e;
        scanf(" %c %d %d", &c, &d, &e);
        cost[d][c-'A'] = min(cost[d][c-'A'], e);
    }

    int S = 36, T = S+1;
    V = T+1;

    int ans = INF;
    rep(mask,1<<10)
    {
        rep(i,V) G[i].clear();

        int lb = 0;

        // source to number
        rep(i,10)
        {
            if(mask>>i&1)
            {
                add_edge(S,i,1,-M);
                add_edge(S,i,INF-1,0);
                ++lb;
            }
            else
            {
                add_edge(S,i,INF,0);
            }
        }

        // number to alphabet
        rep(i,10)rep(j,26)
        {
            add_edge(i,10+j,1,cost[i][j]);
        }

        // alphabet to sink
        bool must[26]={};
        rep(i,26)
        {
            int amask = 0;
            rep(j,10)if(door[j][i]) amask |= 1<<j;

            rep(j,10)
            {
                if((amask>>j&1) && !(mask>>j&1)) must[i]=true;
            }
        }

        rep(i,26)
        {
            if(must[i])
            {
                add_edge(10+i,T,1,-M);
                add_edge(10+i,T,INF-1,0);
                ++lb;
            }
            else
            {
                add_edge(10+i,T,INF,0);
            }
        }

        int cur = 0;

        rep(ff,36)
        {
            int res = min_cost_flow(S,T,1);
            if(res==-191919) break;

            cur += res;
            ans = min(ans,cur+M*lb);
        }

    }


    if(ans==INF) ans = -1;
    printf("%d\n", ans);
    return 0;
}
accuracy: 0.9838709677419355
time_ms: 250
memory_kb: 3280
final_rank: 16

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 = 40; // TODO:initialize
const int INF = 10000; // 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??????t????????????f???????°??????¨???(???????????????-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();
                // dbg(p);
                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 -191919;

        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);
            // dbg(v);
        }

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

const int M = 1000000;
bool door[10][26]={};
int cost[10][26];

int main()
{
    int n;
    scanf(" %d", &n);

    while(n--)
    {
        char c;
        int d;
        scanf(" %c %d", &c, &d);
        door[d][c-'A'] = true;
    }

    fill(cost[0],cost[10],M*100);
    int m;
    scanf(" %d", &m);
    while(m--)
    {
        char c;
        int d,e;
        scanf(" %c %d %d", &c, &d, &e);
        cost[d][c-'A'] = min(cost[d-1][c-'A'], e);
    }

    int S = 36, T = S+1;
    V = T+1;

    int ans = INF;
    rep(mask,1<<10)
    {
        rep(i,V) G[i].clear();

        int lb = 0;

        // source to number
        rep(i,10)
        {
            if(mask>>i&1)
            {
                add_edge(S,i,1,-M);
                add_edge(S,i,INF-1,0);
                ++lb;
            }
            else
            {
                add_edge(S,i,INF,0);
            }
        }

        // number to alphabet
        rep(i,10)rep(j,26)
        {
            add_edge(i,10+j,1,cost[i][j]);
        }

        // alphabet to sink
        bool must[26]={};
        rep(i,26)
        {
            int amask = 0;
            rep(j,10)if(door[j][i]) amask |= 1<<j;

            rep(j,10)
            {
                if((amask>>j&1) && !(mask>>j&1)) must[i]=true;
            }
        }

        rep(i,26)
        {
            if(must[i])
            {
                add_edge(10+i,T,1,-M);
                add_edge(10+i,T,INF-1,0);
                ++lb;
            }
            else
            {
                add_edge(10+i,T,INF,0);
            }
        }

        int cur = 0;

        rep(ff,36)
        {
            int res = min_cost_flow(S,T,1);
            if(res==-191919) break;

            cur += res;
            ans = min(ans,cur+M*lb);
        }

    }


    if(ans==INF) ans = -1;
    printf("%d\n", ans);
    return 0;
}
accuracy: 0.12903225806451613
time_ms: 110
memory_kb: 3268
final_rank: 20

code_snippet: #include <bits/stdc++.h>
#define MAX_V 40
#define INF 1e5
using namespace std;

/*テヲツ慊?・ツーツ湘ィツイツサテァツ板ィテヲツオツ?テ」ツδッテ」ツδシテ」ツつキテ」ツδ」テ」ツδォテ」ツδ陛」ツδュテ」ツつ、テ」ツδ嘉、ツスツソテァツ板ィ) O(F|V||E|)*/

//ティツセツコテ」ツつ津ィツ。ツィテ」ツ?凖ヲツァツ凝ゥツ??、ツスツ?ティツ。ツ古」ツ?催・ツ?暗」ツ??・ツョツケテゥツ?湘」ツ??」ツつウテ」ツつケテ」ツδ暗」ツ??ゥツ??ィツセツコ)
struct edge{int to, cap,cost,rev;};
int V;                         //テゥツ?づァツつケテヲツ閉ー
vector<edge> G[MAX_V];         //テ」ツつーテ」ツδゥテ」ツδ陛」ツ?ョテゥツ堋」テヲツ篠・テ」ツδェテ」ツつケテ」ツδ暗ィツ。ツィテァツ渉セ
int dist[MAX_V];               //テヲツ慊?ァツ淞ュティツキツ敕ゥツ崢「
int prevv[MAX_V],preve[MAX_V]; //テァツ崢エテ・ツ可催」ツ?ョテゥツ?づァツつケテ」ツ?ィティツセツコ

// fromテ」ツ?凝」ツつ液oテ」ツ?クテ・ツ青妥」ツ?凝」ツ??・ツョツケテゥツ?縦apテ」ツ??」ツつウテ」ツつケテ」ツδ?ostテ」ツ?ョティツセツコテ」ツつ津」ツつーテ」ツδゥテ」ツδ陛」ツ?ォティツソツステ・ツ環?」ツ?凖」ツつ凝」ツ??
void add_edge(int from,int to,int cap,int cost){
  G[from].push_back((edge){to,cap,cost,(int)G[to].size()});
  G[to].push_back((edge){from,0,-cost,(int)G[from].size()-1});
}

//sテ」ツ?凝」ツつ液テ」ツ?クテ」ツ?ョテヲツオツ?ゥツ?叔テ」ツ?ョテヲツ慊?・ツーツ湘ィツイツサテァツ板ィテヲツオツ?」ツつ津ヲツアツづ」ツつ?」ツつ?
//テヲツオツ?」ツ?崚」ツ?ェテ」ツ??・ツ?エテ・ツ青?1テ」ツつ津ィツソツ氾」ツ??
int min_cost_flow(int s,int t,int f){
  int res=0;
  while(f>0){
    //テ」ツδ凖」ツδォテ」ツδ榲」ツδウテ」ツδ陛」ツつゥテ」ツδシテ」ツδ嘉ヲツウツ陛」ツ?ォテ」ツつ暗」ツつ?s-tテゥツ鳴禿ヲツ慊?ァツ淞ュティツキツッテ」ツつ津ヲツアツづ」ツつ?」ツつ?
    fill(dist,dist+V,INF);
    dist[s]=0;
    bool update = true;
    while(update){
      update = false;
      for(int v=0; v<V ;v++){
	if(dist[v]==INF) continue;
	for(int i=0; i<G[v].size(); i++){
	  edge &e = G[v][i];
	  if(e.cap > 0 && dist[e.to] > dist[v]+e.cost) {
	    dist[e.to] = dist[v] + e.cost;
	    prevv[e.to] = v;
	    preve[e.to] = i;
	    update = true;
	  }
	}
      }
    }
    if(dist[t]==INF) return -1; //テ」ツ?禿」ツつ古、ツサツ・テ、ツクツ甘ヲツオツ?」ツ?崚」ツ?ェテ」ツ??」ツ??
    
    //sテ「ツ按稚テゥツ鳴禿ァツ淞ュティツキツッテ」ツ?ォテヲツイツソテ」ツ?」テ」ツ?ヲテァツ崢ョテ、ツクツ?ヲツ敖ッテヲツオツ?」ツ??
    int d = f;
    for(int v=t; v!=s; v=prevv[v])d=min(d,G[prevv[v]][preve[v]].cap);
    f -= d;
    res += d*dist[t];
    for(int v=t; v!=s; v=prevv[v]){
      edge &e = G[prevv[v]][preve[v]];
      e.cap -= d;
      G[v][e.rev].cap += d;
    }
  }
  return res;
}

int door[26][10],key[26][10];
int mnalpha[26],mnnum[10];

int S = 26+10,T=S+1;
void mkG(int bit){
  for(int i=0;i<MAX_V;i++)G[i].clear();

  V = 26+10+2;
  //0 -> 25 num
  //26 -> 35 alpha
  
  for(int i=0;i<26;i++)add_edge(S,i,1,0);
  for(int i=0;i<10;i++)add_edge(i+26,T,1,0);

  set<int> used;
  for(int i=0;i<26;i++)
    for(int j=0;j<10;j++){
      if((bit>>j&1)||door[i][j]==0)continue;
      used.insert(i);
    }
  
  for(int i=0;i<26;i++){
    if(used.count(i)==0) add_edge(i,T,1,0);
    else add_edge(i,T,1,mnalpha[i]);
    for(int j=0;j<10;j++){
      if(bit>>j&1)add_edge(i,26+j,1,key[i][j]-mnnum[j]);
    }
  }
}

int main(){
  int n,m;
  cin>>n;
  for(int i=0;i<n;i++){
    char ch;
    int num;
    cin>>ch>>num;
    door[ch-'A'][num] = 1;
  }

  for(int i=0;i<26;i++)for(int j=0;j<10;j++)key[i][j]=INF;
  for(int i=0;i<10;i++) mnnum[i]=INF;
  for(int i=0;i<26;i++) mnalpha[i] = INF;
  
  cin>>m;  
  for(int i=0;i<m;i++){
    char ch;
    int num,cost;
    cin>>ch>>num>>cost;
    key[ch-'A'][num] = min(key[ch-'A'][num],cost);
    mnnum[num] = min(cost,mnnum[num]);
    mnalpha[ch-'A']=min(cost,mnalpha[ch-'A']);
  }

  int ans = INF;
  for(int i=0;i<(1<<10);i++){
    mkG(i);
    int cost=0;
    for(int j=0;j<10;j++)if(i>>j&1) cost+=mnnum[j];
    int res = min_cost_flow(S,T,26);
    if(res!=-1)ans=min(ans,cost+res);
  }
  if(ans>=INF) ans=-1;
  cout<<ans<<endl;
  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 3172
final_rank: 3

code_snippet: #include <bits/stdc++.h>
#define MAX_V 40
#define INF 1e5
using namespace std;

/*????°??????¨???(???????????£????????????????????¨) O(F|V||E|)*/

//????????¨????§???????(???????????????????????????????????????)
struct edge{int to, cap,cost,rev;};
int V;                         //????????°
vector<edge> G[MAX_V];         //??°???????????£??\???????????¨???
int dist[MAX_V];               //???????????¢
int prevv[MAX_V],preve[MAX_V]; //??´??????????????¨???

// from??????to??????????????????cap????????????cost???????????°????????????????????????
void add_edge(int from,int to,int cap,int cost){
  G[from].push_back((edge){to,cap,cost,(int)G[to].size()});
  G[to].push_back((edge){from,0,-cost,(int)G[from].size()-1});
}

//s??????t????????????f???????°??????¨???????±???????
//??????????????´???-1?????????
int min_cost_flow(int s,int t,int f){
  int res=0;
  while(f>0){
    //????????????????????????????????????,s-t????????????????±???????
    fill(dist,dist+V,INF);
    dist[s]=0;
    bool update = true;
    while(update){
      update = false;
      for(int v=0; v<V ;v++){
	if(dist[v]==INF) continue;
	for(int i=0; i<G[v].size(); i++){
	  edge &e = G[v][i];
	  if(e.cap > 0 && dist[e.to] > dist[v]+e.cost) {
	    dist[e.to] = dist[v] + e.cost;
	    prevv[e.to] = v;
	    preve[e.to] = i;
	    update = true;
	  }
	}
      }
    }
    if(dist[t]==INF) return -1; //????????\??????????????????
    
    //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*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 door[26][10],key[26][10];
int mnalpha[26],mnnum[10];

int S = 26+10,T=S+1;
void mkG(int bit){
  for(int i=0;i<MAX_V;i++)G[i].clear();

  V = 26+10+2;
  //0 -> 25 num
  //26 -> 35 alpha
  
  for(int i=0;i<26;i++)add_edge(S,i,1,0);
  for(int i=0;i<10;i++)add_edge(i+26,T,1,0);

  set<int> used;
  for(int i=0;i<26;i++)
    for(int j=0;j<10;j++){
      if((bit>>j&1)||door[i][j]==0)continue;
      used.insert(i);
    }
  
  for(int i=0;i<26;i++){
    if(used.count(i)==0) add_edge(i,T,1,0);
    else add_edge(i,T,1,mnalpha[i]);
    for(int j=0;j<10;j++){
      if(bit>>j&1)add_edge(i,26+j,1,key[i][j]-mnnum[j]);
    }
  }
}

int main(){
  int n,m;
  cin>>n;
  for(int i=0;i<n;i++){
    char ch;
    int num;
    cin>>ch>>num;
    door[ch-'A'][num] = 1;
  }

  for(int i=0;i<26;i++)for(int j=0;j<10;j++)key[i][j]=INF;
  for(int i=0;i<10;i++) mnnum[i]=INF;
  for(int i=0;i<26;i++) mnalpha[i] = INF;
  
  cin>>m;  
  for(int i=0;i<m;i++){
    char ch;
    int num,cost;
    cin>>ch>>num>>cost;
    key[ch-'A'][num] = min(key[ch-'A'][num],cost);
    mnnum[num] = min(cost,mnnum[num]);
    mnalpha[ch-'A']=min(cost,mnalpha[ch-'A']);
  }

  int ans = INF;
  for(int i=0;i<(1<<10);i++){
    mkG(i);
    int cost=0;
    for(int j=0;j<10;j++)if(i>>j&1) cost+=mnnum[j];
    int res = min_cost_flow(S,T,26);
    if(res!=-1)ans=min(ans,cost+res);
  }
  if(ans>=INF) ans=-1;
  cout<<ans<<endl;
  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 3184
final_rank: 4

code_snippet: #include<stdio.h>
#include<algorithm>
using namespace std;
int c[30][12];
int d[30][12];
char in[30];
int pow3[12];
int dp[30][60000];
int u[30];
int main(){
	int a;
	scanf("%d",&a);
	pow3[0]=1;
	for(int i=1;i<12;i++)pow3[i]=pow3[i-1]*3;
	for(int i=0;i<a;i++){
		int p,q;
		scanf("%s%d",in,&q);
		p=in[0]-'A';
		c[p][q]=1;
		u[p]=1;
	}
	int b;scanf("%d",&b);
	for(int i=0;i<30;i++)for(int j=0;j<12;j++)
		d[i][j]=99999999;
	for(int i=0;i<b;i++){
		int p,q,r;
		scanf("%s%d%d",in,&q,&r);
		p=in[0]-'A';
		d[p][q]=min(d[p][q],r);
	}
	for(int i=0;i<30;i++)for(int j=0;j<60000;j++)
		dp[i][j]=99999999;
	dp[0][0]=0;
	for(int i=0;i<26;i++){
		for(int j=0;j<pow3[10];j++){
			for(int k=0;k<10;k++){
				int to=j-j%pow3[k+1]/pow3[k]*pow3[k]+pow3[k]*2;
				dp[i][to]=min(dp[i][to],dp[i][j]+d[i][k]);
				dp[i+1][to]=min(dp[i+1][to],dp[i][j]+d[i][k]);
			}
			int to=j;
			for(int k=0;k<10;k++){
				if(j%pow3[k+1]/pow3[k]==0&&c[i][k]){
					to+=pow3[k];
				}
			}
			dp[i+1][to]=min(dp[i+1][to],dp[i][j]);
		}
	}
	int ret=99999999;
	for(int i=0;i<pow3[10];i++){
		bool ok=true;
		for(int j=0;j<10;j++)if(i%pow3[j+1]/pow3[j]==1)ok=false;
		if(ok)ret=min(ret,dp[26][i]);
	}
	if(ret>9999999)printf("-1\n");
	else printf("%d\n",ret);
}
accuracy: 1
time_ms: 300
memory_kb: 8064
final_rank: 13

code_snippet: #include<bits/stdc++.h>
#define chmin(a,b) a=min(a,b)
using namespace std;
const int INF = 1e7;

struct edge{
  int to, cap, cost, rev;
  edge(int a,int b,int c,int d):to(a),cap(b),cost(c),rev(d){}
};
typedef vector< vector<edge> > graph;

void add_edge(graph &g, int s, int t, int cap, int cost){
  g[s].push_back(edge(t,cap,cost,g[t].size()));
  g[t].push_back(edge(s,0,-cost,g[s].size()-1));
}

int Optimize(int digit, int alpha, const vector<int> &cost){
  graph g(38);
  for(int i=0;i<10;i++){
    for(int j=0;j<26;j++){
      if(cost[j*10+i]!=INF){
	add_edge(g,i+1,j+11,1,cost[j*10+i]);
      }
    }
  }

  int base = 0;
  for(int i=0;i<10;i++){
    add_edge(g,0,i+1,100,0);
    if( (digit>>i)&1 )add_edge(g,0,i+1,1,-INF), base += INF;
  }

  for(int i=0;i<26;i++){
    add_edge(g,i+11,37,100,0);
    if( (alpha>>i)&1 )add_edge(g,i+11,37,1,-INF), base += INF;
  }

  int res = INF, sum = 0;
  vector<int> prevv(38),preve(38);
  for(;;){
    vector<int> d(38,INF), inQ(38,0);
    queue<int> q;
    d[0] = 0; q.push(0); inQ[0] = 1;

    while(q.size()){
      int v = q.front(); q.pop(); inQ[v] = 0;

      for(int i=0;i<(int)g[v].size();i++){
	edge &e = g[v][i];
	if(e.cap > 0 && d[e.to] > d[v] + e.cost){
	  d[e.to] = d[v] + e.cost;
	  if(!inQ[e.to])q.push(e.to), inQ[e.to] = 1;
	  prevv[e.to] = v;
	  preve[e.to] = i;
	}
      }
    }

    if(d[37] == INF)break;

    sum += d[37];
    chmin(res, sum + base);
    for(int v=37;v!=0;v=prevv[v]){
      edge &e = g[prevv[v]][preve[v]];
      e.cap--;
      g[v][e.rev].cap++;
    }
  }

  return res;
}

int main(){
  int n,m;

  scanf("%d",&n);
  vector<int> door(260,0), card(260,INF);
  for(int i=0;i<n;i++){
    char a; int b;
    scanf(" %c %d",&a,&b);
    door[(int)(a-'A')*10+b] = 1;
  }

  scanf("%d",&m);
  for(int i=0;i<m;i++){
    char c; int d,e;
    scanf(" %c %d%d",&c,&d,&e);
    card[(int)(c-'A')*10+d] = min(card[(int)(c-'A')*10+d], e);
  }

  int ans = INF;
  for(int digit=0;digit<(1<<10);digit++){
    int alpha = 0;
    for(int i=0;i<10;i++){
      if( ((digit>>i)&1) == 0){
	for(int j=0;j<26;j++){
	  alpha |= door[j*10 + i]<<j;
	}
      }
    }
    ans = min(ans,Optimize(digit,alpha,card));
  }
  
  if(ans==INF)puts("-1");
  else printf("%d\n",ans);
}
accuracy: 1
time_ms: 900
memory_kb: 1200
final_rank: 7

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

#define rep2(i,a,b) for(int i=(a);i<(b);i++)
#define rep(i,n) rep2(i,0,n)
#define sz(x) ((int)(x).size())
#define MAX_V 40
int INF = 1e9;
const int MM = 1234567;
typedef pair<int,int> P;

struct edge{ int to, cap,cost,rev; };

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

int dbg = 0;

void add_edge(int from,int to,int cap,int cost){
	if(dbg){
		cout<<"ae "<<from<<" "<<to<<" "<<cap<<" "<<cost<<endl;
	}
	G[from].push_back((edge){to,cap,cost,(int)G[to].size()});
	G[to].push_back({from,0,-cost,(int)G[from].size()-1});
}
long min_cost_flow(int s,int t,int f){
	long res = 0;
	fill(h,h+V,INF);
	h[s] = 0;
	while(true){
		int flag = 0;
		//cout << "--" << endl;
		for(int v = 0 ; v < V ; v++){
			for(int i = 0 ; i < G[v].size(); i++){
				edge &e = G[v][i];
				if( e.cap > 0 && h[e.to] > h[v] + e.cost){
					h[e.to] = h[v] + e.cost;
					flag = true;
					//cout << "==" << endl;
				}
			}
		}
		if(!flag) break;
	}
	if(dbg){rep(i,V)cout<<i<<": "<<h[i]<<" "<<endl;}
	while( f > 0 ){
		fill(dist,dist+V,INF);
		priority_queue<P,vector<P>,greater<P> > que;
		fill(dist,dist+V,INF);
		dist[s] = 0;
		que.push(P(0,s));
		while( !que.empty() ){
			P p = que.top(); que.pop();
			int v = p.second;
			if( dist[v] < p.first ) continue;
			for(int i = 0 ; i < G[v].size(); i++){
				edge &e = G[v][i];
				if( e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to] ){
					dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
					prevv[e.to] = v;
					preve[e.to] = i;
					que.push(P(dist[e.to],e.to));
				}
			} 
		}
		if(dbg){rep(i,V)if(dist[i]<INF)cout<<i<<": "<<dist[i]<<" "<<endl;}

		if( dist[t] == INF){
			if(dbg)cout<<"A!"<<endl;
			return res; // !!!
		}
		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);
		}

		if(h[t] >= 0){ // !!!
			if(dbg)cout<<"B!"<<endl;
			return res;
		}

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


void add_edge2(int from, int to, int cost, int mincap, int maxcap){
	if(dbg)cerr<<from<<" "<<to<<" "<<cost<<" "<<mincap<<" "<<maxcap<<endl;
	bsum += mincap;
	add_edge(from, to, maxcap - mincap, cost);
	add_edge(from, to, mincap, cost-MM);
}

int N, M;
int cond[11][27];
int card[11][27];

int main(){
	cin>>N;
	rep(i,N){
		//cin>>a[i]>>b[i];
		char a; int b;
		cin>>a>>b;
		cond[b][a-'A'] = 1;
	}
	/*rep(i,10)rep(j,26){
		cout<<cond[i][j]<<(j==25?"\n":" ");
	}*/
	rep(i,10)rep(j,26) card[i][j] = INF;
	cin>>M;
	rep(i,M){
		char c; int d; int e;
		cin>>c>>d>>e;
		card[d][c-'A'] = min(card[d][c-'A'], e);
	}
	/*rep(i,10)rep(j,26){
		cout<<cond[i][j]<<(j==25?"\n":" ");
	}*/
	/*rep(i,10)rep(j,26){
		cout<<card[i][j]<<(j==25?"\n":" ");
	}*/
	int ans = INF;
	rep(mask,1<<10){ // buy
		//if(mask == (1<<3)) dbg = 1; else dbg = 0;

		V = 38;
		bsum = 0;
		rep(i,V)G[i].clear();
		int s = 36, t = 37;
		rep(i,10)if(mask>>i&1){
			add_edge2(s, 0+i, 0, 1, 36);
		}
		int survive[26] = {};
		rep(i,10)rep(j,26){
			if(cond[i][j] && !(mask>>i&1)){
				survive[j] = 1;
			}
		}
		if(dbg){
			rep(j,26)cout<<survive[j];cout<<endl;
		}
		rep(j,26)if(survive[j]){
			add_edge2(10+j, t, 0, 1, 36);
		}
		rep(i,10)rep(j,26)if(card[i][j] < INF){
			if(!(mask>>i&1)) continue;
			if(survive[j]){
				add_edge2(0+i, 10+j, card[i][j], 0, 1);
			}else{
				add_edge2(0+i, t, card[i][j], 0, 1);
			}
		}

		int res = min_cost_flow(s, t, 36);
		if(dbg)cout<<res<<" "<<bsum<<" "<<res+MM*bsum<<endl;
		res += MM * bsum;
		ans = min(ans, res);
	}
	if(ans >= MM)cout<<-1<<endl;
	else cout<<ans<<endl;
}
accuracy: 1
time_ms: 160
memory_kb: 1280
final_rank: 2

code_snippet: #include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=(a);i<(int)(b);i++)
#define REP(i,b) FOR(i,0,b)
#define F first
#define S second
#define X real()
#define Y imag()
#define PB push_back 
#define BE(c) c.begin(),c.end()
using namespace std;
typedef long long LL;
typedef complex<int> cld;
typedef LL ut;
typedef vector<ut> VI;
typedef pair<ut,ut> pr;
typedef vector<pr> Vpr;
typedef vector<ut,pr> ppr;
typedef priority_queue<pr,Vpr,greater<pr> > PQ;
typedef vector<ppr> Vppr;
const int bitSIZE=1<<10;
const int SIZE=1+1e+5;
const int INF=1+1e+7;
const int SEGSIZE=3*1e+8;
bool need[bitSIZE][27];
char str[SIZE];
int num[SIZE];
int N,M;
int cards[27][10];
int minC[27],minN[10];
int DP[27][bitSIZE];
void calcNeed(int bit){
	REP(i,N){
		if(bit&(1<<num[i])) continue;
		else need[bit][str[i]-'A']=true;
	}
}
int solve(int bit){
	REP(i,27)
		REP(j,bitSIZE)
			DP[i][j]=INF;
	int bitnum=0;
	int grundy[10]={};
	int ingrund[10]={};
	DP[0][0]=0;
	REP(i,10){
		if(bit&(1<<i))
			grundy[bitnum++]=i;
	}
	REP(i,'Z'-'A'+1){
		if(need[bit][i])
			REP(k,1<<bitnum)
				REP(j,bitnum){
					DP[i+1][k|(1<<j)]=min(DP[i+1][k|(1<<j)],DP[i][k]+cards[i][grundy[j]]);
					DP[i+1][k]=min(DP[i+1][k],DP[i][k]+minC[i]);
				}
		else
			REP(k,1<<bitnum)
				DP[i+1][k]=DP[i][k];
	}
	int ans=INF;
	REP(i,1<<bitnum){
		int sum=0;
		REP(j,bitnum)
			if((i&(1<<j))==0)
				sum+=minN[grundy[j]];
		ans=min(ans,DP['Z'-'A'+1][i]+sum);
	}
	return ans;
}
int main(){
	cin >> N;
	char c;
	int n,cost;
	REP(i,N)
		cin >> str[i] >> num[i];
	REP(i,bitSIZE)
		calcNeed(i);
	REP(i,27)
		REP(j,11)
			cards[i][j]=INF;
	REP(i,'Z'-'A'+1)
		minC[i]=INF;
	REP(i,10)
		minN[i]=INF;
	cin >> M;
	REP(i,M){
		cin >> c >> n >> cost;
		cards[c-'A'][n]=min(cost,cards[c-'A'][n]);
		minC[c-'A']=min(minC[c-'A'],cost);
		minN[n]=min(minN[n],cost);
	}
	int ans=INF;
	REP(i,bitSIZE)
		ans=min(ans,solve(i));
	if(ans>=INF) cout << -1 << endl;
	else cout << ans << endl;

}
accuracy: 1
time_ms: 80
memory_kb: 1352
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (int)n; ++i)
#define SZ(s) ((int)(s.size()))
#define pb push_back
#define mp make_pair
#define F first
#define S second
#define ALL(a) (a).begin(), (a).end()
typedef pair<int,int> PI;
typedef long long ll;

int app[100][100];
ll cost[100][100];

int main(int argc, char *argv[])
{
  int n;
  cin >> n;
  rep(i, n){
    char c;
    int b;
    cin >> c >> b;
    app[c-'A'][b] = 1;
  }

  int m;
  cin >> m;
  rep(i, 100) rep(j, 100) cost[i][j] = 1LL << 40LL;
  
  rep(j, m){
    char c;
    int b;
    ll e;
    cin >> c >> b >> e;
    cost[c-'A'][b] = min(cost[c-'A'][b], e);
  }
  
  ll ans = 1LL << 40;
  
  
  rep(used, 1 << 10){
    static ll dp[2][1<<10] = {};
    
    int needalpha[30] = {};
    rep(i, 26) rep(j, 10){
      if(app[i][j] && ((~used>>j)&1))
        needalpha[i] = 1;
    }
    
    rep(i,2) rep(k, 1<< 10) dp[i][k] = 1LL << 40LL;
    
    int cur = 0;
    dp[cur][0] = 0;
    rep(i, 26){
      int ne = 1 - cur;
      rep(j, 1 << 10) dp[ne][j] = 1LL << 40LL;
      
      if(!needalpha[i]){
        rep(j, 1 << 10) dp[ne][j] = min(dp[ne][j], dp[cur][j]);
      }

      // rep(j, 1 << 10) rep(k, 10){
      //   if(j&(1<<k)) continue;
      //   dp[cur][j|(1<<k)] = min(dp[cur][j|(1<<k)], dp[cur][j] + cost[i-1][k]);
      // }
      
      rep(j, 1 << 10){
        rep(k, 10){
          dp[ne][j|(1<<k)] = min(dp[ne][j|(1<<k)], dp[cur][j] + cost[i][k]);
        }
      }
      
      rep(j, 1 << 10) rep(k, 10){
        //if(j&(1<<k)) continue;
        dp[ne][j|(1<<k)] = min(dp[ne][j|(1<<k)], dp[ne][j] + cost[i][k]);
      }
      
      cur = 1 - cur;
    }
    
    rep(i, 1 << 10){
      if((i&used) == used){
        ans = min(ans, dp[cur][i]);
        // if(ans == 7){
        //   cout << used << ' ' << i << endl;
        //   return 0;
        // }
      }
    }
  }
  
  if(ans >= (1LL << 40LL)) cout << -1 << endl;
  else cout << ans << endl;
  
  return 0;
}
accuracy: 1
time_ms: 1120
memory_kb: 1276
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (int)n; ++i)
#define SZ(s) ((int)(s.size()))
#define pb push_back
#define mp make_pair
#define F first
#define S second
#define ALL(a) (a).begin(), (a).end()
typedef pair<int,int> PI;
typedef long long ll;

int app[100][100];
ll cost[100][100];
int main(int argc, char *argv[])
{
  int n;
  cin >> n;
  rep(i, n){
    char c;
    int b;
    cin >> c >> b;
    app[c-'A'][b] = 1;
  }

  int m;
  cin >> m;
  rep(i, 100) rep(j, 100) cost[i][j] = 1LL << 40LL;
  
  rep(j, m){
    char c;
    int b;
    ll e;
    cin >> c >> b >> e;
    cost[c-'A'][b] = min(cost[c-'A'][b], e);
  }
  
  ll ans = 1LL << 40;

  ll dp[2][1<<10] = {};
  
  rep(used, 1 << 10){
    int needalpha[30] = {};
    rep(i, 26) rep(j, 10){
      if(app[i][j] && ((~used>>j)&1))
        needalpha[i] = 1;
    }
    
    rep(i,2) rep(k, 1<< 10) dp[i][k] = 1LL << 40LL;
    
    int cur = 0;
    dp[cur][0] = 0;
    rep(i, 26){
      int ne = 1 - cur;
      rep(j, 1 << 10) dp[ne][j] = 1LL << 40LL;
      if(!needalpha[i]){
        rep(j, 1 << 10) dp[ne][j] = min(dp[ne][j], dp[cur][j]);
      }
      
      rep(j, 1 << 10){
        rep(k, 10){
          dp[ne][j|(1<<k)] = min(dp[ne][j|(1<<k)], dp[cur][j] + cost[i][k]);
        }
      }
      
      cur = 1 - cur;
    }
    
    rep(i, 1 << 10){
      if((i&used) == used)
        ans = min(ans, dp[cur][i]);
    }
  }

  if(ans >= (1LL << 40LL)) cout << -1 << endl;
  else cout << ans << endl;
  return 0;
}
accuracy: 0.12903225806451613
time_ms: 510
memory_kb: 1280
final_rank: 19