Problem:
Problem 08:
Provident Housewife
主婦の琴子はこの不況のさなか食費を抑えることに闘志を燃やしていました。毎朝新聞広告を必ずチェック。買う物リストと最も安く売られているお店をしっかりリストアップして、お店をはしごしながら、エプロン・サンダルという戦闘スタイルで自転車をこぎこぎ買い物に行きます。
そこで夫のあなたは少しでも琴子の役に立とうと、得意のプログラミングで家計簿プログラムを作成することにしました。プログラムは、各スーパーに売っている品物の名前と値段（円）、琴子が必要な品物を入力し、全ての品物を集めるための最小金額を出力します。
琴子は家を出て必要な品物を集め、家に戻ってこなければなりません。
そこで、琴子を気遣ったあなたは、最小金額が同じになる買い物ルートが複数ある場合も考慮して、より距離が短くなるルートの距離を報告する機能を追加することにしました。従って、プログラムはスーパー・家間を繋ぐ道の情報も入力します。
スーパーの数を
n
とし、各スーパーにはそれぞれ 1 から
n
までの番号が割り当てられます。さらに琴子の家を 0 番とします。道の情報はこれらの番号のペアとその距離（整数）で与えられます。
Input
入力として複数のデータセットが与えられます。各データセットの形式は以下の通りです：
n
（スーパーの数：整数）
k
1
name
1
value
1
name
2
value
2
. . .
name
k
1
value
k
1
（1 番目のスーパーにある品物の種類の数、1つ目の品物名と値段、2つ目の品物名と値段,,,：整数と文字列の空白区切り）
k
2
name
1
value
1
name
2
value
2
. . .
name
k
2
value
k
2
（2 番目のスーパーにある品物の種類の数、1つ目の品物名と値段、2つ目の品物名と値段,,,：整数と文字列の空白区切り）
.
.
k
n
name
1
value
1
name
2
value
2
. . .
name
k
n
value
k
n
（
n
番目のスーパーにある品物の種類の数、1つ目の品物名と値段、2つ目の品物名と値段,,,：整数と文字列の空白区切り）
q
（必要な品物の数：整数）
name
1
（1 つ目の必要な品物の名前：文字列）
name
2
（2 つ目の必要な品物の名前：文字列）
.
.
name
q
（
q
つ目の必要な品物の名前：文字列）
m
（道の数：整数）
s
1
t
1
d
1
（1 本目の道の情報：空白区切りの整数）
s
2
t
2
d
2
（2 本目の道の情報：空白区切りの整数）
.
.
s
m
t
m
d
m
（
m
本目の道の情報：空白区切りの整数）
s
i
t
i
d
i
は
s
i
番目のスーパー（または家）と
t
i
番目のスーパー（または家）が双方向に行き来することができ、その距離が
d
i
であることを示します。
家から（スーパーを経由して）全てのスーパーへ行くことができるような道が与えられます。
n
は 10 以下であり、
q
は 15 以下とします。
k
i
は 100 以下であり、
品物名の文字列は 20文字を越ず、品物の値段は 10000 を越えません。
また、道の長さは 1000 を越えません。
n
が 0 のとき、入力の終わりとします。
Output
各データセットについて、最小の金額と距離を１つの空白で区切って１行に出力して下さい。ただし、必要な品物を全て集められない場合は "
impossible
" と出力して下さい。
Sample Input
3
3 apple 100 banana 200 egg 300
3 apple 150 banana 100 cola 200
3 apple 100 banana 150 cola 200
3
apple
banana
cola
5
0 2 4
0 1 3
0 3 3
1 2 3
2 3 5
3
3 apple 100 banana 200 egg 300
3 apple 150 banana 100 cola 200
3 apple 100 banana 150 cola 200
4
apple
banana
cola
jump
5
0 2 4
0 1 3
0 3 3
1 2 3
2 3 5
0
Output for the Sample Input
400 10
impossible

Submitted solutions:

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

// 大きな値として INF を定義
static const int INF = 1e9;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    while (true) {
        int n;
        cin >> n;
        if (!cin || n == 0) break;  // n==0 で終了

        // スーパー 1..n, 家を 0 としてグラフのノードは 0..n
        // 先に各スーパーが売る品物情報を読み取るプレースホルダ
        vector<unordered_map<string,int>> price(n+1);
        for (int i = 1; i <= n; i++){
            int ki;
            cin >> ki;
            // ki 個の (name, value) ペアをマップに格納
            while (ki--){
                string name;
                int value;
                cin >> name >> value;
                price[i][name] = value;
            }
        }

        // 必要な品物 q とその名前を読み込み
        int q;
        cin >> q;
        vector<string> need(q);
        for (int i = 0; i < q; i++){
            cin >> need[i];
        }

        // グラフの辺情報を読み込む
        int m;
        cin >> m;
        // 隣接行列 dist[u][v]: 最短距離
        int N = n + 1;
        vector<vector<int>> dist(N, vector<int>(N, INF));
        for (int i = 0; i < N; i++){
            dist[i][i] = 0;
        }
        // m 本の道路
        for (int i = 0; i < m; i++){
            int s, t, d;
            cin >> s >> t >> d;
            // 双方向
            dist[s][t] = min(dist[s][t], d);
            dist[t][s] = min(dist[t][s], d);
        }

        // Floyd-Warshall で全点対最短路を計算
        for (int k = 0; k < N; k++){
            for (int i = 0; i < N; i++){
                if (dist[i][k] == INF) continue;
                for (int j = 0; j < N; j++){
                    dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
                }
            }
        }

        // 各スーパー i(1..n) が必要品目を何番目に売っているかをインデックス化
        // priceShop[i][j] = スーパー i が need[j] を売る時の価格、売らないなら INF
        vector<vector<int>> priceShop(n+1, vector<int>(q, INF));
        bool impossible = false;
        for (int j = 0; j < q; j++){
            const string &item = need[j];
            bool found = false;
            for (int i = 1; i <= n; i++){
                auto it = price[i].find(item);
                if (it != price[i].end()){
                    priceShop[i][j] = it->second;
                    found = true;
                }
            }
            if (!found){
                // ある必要品がどの店にもない → impossible
                impossible = true;
            }
        }
        if (impossible){
            cout << "impossible\n";
            continue;
        }

        // ビットマスクでショップの部分集合を横断
        // 全品目をカバーする最良 (money, distance)
        long long bestMoney = LLONG_MAX;
        int bestDist = INF;

        int fullMask = (q==0?0: (1<<q) - 1);

        // subsets: 1..(1<<n)-1
        for (int s = 1; s < (1<<n); s++){
            // まずこの店群 s が全品目をカバーしているかチェックしつつ、
            // 各品目の最安価格を集めて money を計算
            long long money = 0;
            bool ok = true;
            for (int j = 0; j < q; j++){
                int cheapest = INF;
                // s の各ビット i が立っていたら店 i+1 をチェック
                for (int i = 0; i < n; i++){
                    if (s & (1<<i)){
                        cheapest = min(cheapest, priceShop[i+1][j]);
                    }
                }
                if (cheapest == INF){
                    ok = false;
                    break;
                }
                money += cheapest;
            }
            if (!ok) continue;
            // money がすでに最良を超えていれば旅行距離計算不要
            if (money > bestMoney) continue;

            // この集合 s の店を巡る最短の往復距離を TSP で求める
            // shops: s に入る店リスト
            vector<int> shops;
            for (int i = 0; i < n; i++){
                if (s & (1<<i)) shops.push_back(i+1);
            }
            int k = shops.size();
            // DP[mask][i]: mask ビット集合の店を訪問済で最後が shops[i]
            static int dp[1<<10][10];
            const int INF2 = 1e9;
            for (int mask = 0; mask < (1<<k); mask++){
                for (int i = 0; i < k; i++){
                    dp[mask][i] = INF2;
                }
            }
            // 初期状態：家(0)→shops[i]
            for (int i = 0; i < k; i++){
                int node = shops[i];
                if (dist[0][node] < INF)
                    dp[1<<i][i] = dist[0][node];
            }
            // TSP ビット DP
            for (int mask = 1; mask < (1<<k); mask++){
                for (int last = 0; last < k; last++){
                    if (!(mask & (1<<last))) continue;
                    int cur = dp[mask][last];
                    if (cur == INF2) continue;
                    // 次に訪れる店 nxt
                    for (int nxt = 0; nxt < k; nxt++){
                        if (mask & (1<<nxt)) continue;
                        int d2 = dist[ shops[last] ][ shops[nxt] ];
                        if (d2 == INF) continue;
                        int nm = mask | (1<<nxt);
                        dp[nm][nxt] = min(dp[nm][nxt], cur + d2);
                    }
                }
            }
            // 完全訪問 mask_end = (1<<k)-1 から家(0)へ戻る
            int mask_end = (1<<k) - 1;
            int tourDist = INF2;
            for (int i = 0; i < k; i++){
                int d2 = dist[ shops[i] ][ 0 ];
                if (d2 == INF) continue;
                tourDist = min(tourDist, dp[mask_end][i] + d2);
            }
            if (tourDist == INF2) continue;

            // (money, tourDist) で比較・更新
            if (money < bestMoney || (money == bestMoney && tourDist < bestDist)){
                bestMoney = money;
                bestDist = tourDist;
            }
        }

        if (bestMoney == LLONG_MAX){
            cout << "impossible\n";
        } else {
            cout << bestMoney << " " << bestDist << "\n";
        }
    }

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3448
final_rank: 7

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

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

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n;
    while (cin >> n, n) {
        vector<map<string, int>> v(n);
        for (int i = 0; i < n; ++i) {
            int k, val;
            cin >> k;
            for (int j = 0; j < k; ++j) {
                string s;
                cin >> s >> val;
                v[i][s] = val;
            }
        }
        int r;
        cin >> r;
        vector<string> need(r);
        for (int i = 0; i < r; ++i) {
            cin >> need[i];
        }
        int m;
        cin >> m;
        vector<vector<int>> dist(n + 1, vector<int>(n + 1, 1e9));
        for (int i = 0; i < m; ++i) {
            int s, t, d;
            cin >> s >> t >> d;
            dist[s][t] = dist[t][s] = d;
        }
        for (int k = 0; k <= n; ++k) {
            for (int i = 0; i <= n; ++i) {
                for (int j = 0; j <= n; ++j) {
                    dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
                }
            }
        }
        vector<vector<int>> dp(1 << (n + 1), vector<int>(n + 1, 1e9));
        dp[0][0] = 0;
        for (int i = 0; i < (1 << (n + 1)); ++i) {
            for (int j = 0; j <= n; ++j) {
                if (dp[i][j] == 1e9) continue;
                for (int k = 0; k <= n; ++k) {
                    if ((1 << k) & i) continue;
                    dp[i + (1 << k)][k] = min(dp[i + (1 << k)][k], dp[i][j] + dist[j][k]);
                }
            }
        }
        pair<int, int> res = {1e9, 1e9};
        for (int i = 0; i < (1 << (n + 1)); ++i) {
            vector<int> a(r, 1e9);
            for (int j = 1; j <= n; ++j) {
                if (i & (1 << j)) {
                    for (int k = 0; k < r; ++k) {
                        if (v[j - 1].find(need[k]) != v[j - 1].end()) {
                            a[k] = min(a[k], v[j - 1][need[k]]);
                        }
                    }
                }
            }
            int sum = 0;
            bool ok = true;
            for (int j = 0; j < r; ++j) {
                if (a[j] == 1e9) {
                    ok = false;
                    break;
                }
                sum += a[j];
            }
            if (ok) res = min(res, {sum, dp[i][0]});
        }
        if (res.first == 1e9) cout << "impossible\n";
        else cout << res.first << " " << res.second << "\n";
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3664
final_rank: 11

code_snippet: #include<bits/stdc++.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;


int N,num_need,E;
int POW[17];
int num_item[10];
int first_value[10][100],value[10][15];
int min_dist[11][11];
int TSP[1024][10];
char name[10][100][21],need[15][21];


bool strCmp(char* base, char* comp){
	int length1,length2;
	for(length1=0;base[length1] != '\0';length1++);
	for(length2=0;comp[length2] != '\0';length2++);
	if(length1 != length2)return false;

	for(int i=0;base[i] != '\0'; i++){
		if(base[i] != comp[i])return false;
	}
	return true;
}

void func(){

	//各スーパーの販売品情報を取得
	for(int i = 0; i < N; i++){
		scanf("%d",&num_item[i]);
		for(int k = 0; k < num_item[i]; k++){
			scanf("%s %d",name[i][k],&first_value[i][k]);
		}
	}

	scanf("%d",&num_need);

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

	//各店の販売品情報を、必要な商品情報で更新する
	for(int i = 0; i < N; i++){
		for(int k = 0; k < num_need; k++){
			value[i][k] = -1; //-1:該当商品なし
		}
	}

	for(int i = 0; i < num_need; i++){ //必要な商品のループ
		for(int k = 0; k < N; k++){ //店のループ
			for(int p = 0; p < num_item[k]; p++){ //店の商品のループ
				if(!strCmp(name[k][p],need[i]))continue;

				value[k][i] = first_value[k][p]; //i番目の商品の値段を記録

				break;
			}
		}
	}

	for(int i = 0; i <= N; i++){
		for(int k = 0; k <= N; k++){
			if(i != k){
				min_dist[i][k] = BIG_NUM;
			}else{
				min_dist[i][k] = 0;
			}
		}
	}

	scanf("%d",&E);

	//★グラフでは、各店を1オリジンで扱う★
	int from,to,dist;
	for(int loop = 0; loop < E; loop++){
		scanf("%d %d %d",&from,&to,&dist);
		min_dist[from][to] = dist;
		min_dist[to][from] = dist;
	}

	//ワーシャルフロイド
	for(int mid = 0; mid <= N; mid++){
		for(int start = 0; start <= N; start++){
			if(min_dist[start][mid] == BIG_NUM)continue;
			for(int goal = 0; goal <= N; goal++){
				if(min_dist[mid][goal] == BIG_NUM)continue;

				min_dist[start][goal] = min(min_dist[start][goal],min_dist[start][mid]+min_dist[mid][goal]);
			}
		}
	}

	int ans_dist = BIG_NUM,ans_cost = BIG_NUM,tmp_dist,tmp_cost;
	int my_house = 0,next_state,next_cost;

	bool is_visit_store[N];
	int min_item[num_need];

	for(int state = 1; state < POW[N]; state++){ //訪れる店の集合のループ
		//今回のTSPで訪れる店を計算する
		for(int loop = 0; loop < N; loop++){
			if(state & (1 << loop)){
				is_visit_store[loop] = true;
			}else{
				is_visit_store[loop] = false;
			}
		}
		for(int i = 0; i < num_need; i++)min_item[i] = BIG_NUM;

		//最小価格を求めつつ、今回訪れる店の組合せで欲しい商品が揃うか調べる
		for(int i = 0; i < num_need; i++){
			for(int k = 0; k < N; k++){
				if(!is_visit_store[k])continue;

				if(value[k][i] != -1){
					min_item[i] = min(min_item[i],value[k][i]);
				}
			}
		}

		tmp_cost = 0;
		for(int i = 0; i < num_need; i++){
			if(min_item[i] == BIG_NUM){
				tmp_cost = BIG_NUM;
				break;
			}
			tmp_cost += min_item[i];
		}

		if(tmp_cost == BIG_NUM || tmp_cost > ans_cost)continue;

		for(int i = 0; i <= state; i++){
			for(int k = 0; k < N; k++)TSP[i][k] = BIG_NUM;
		}

		for(int first_store = 0; first_store < N; first_store++){
			if(!is_visit_store[first_store])continue;
			TSP[POW[first_store]][first_store] = min_dist[my_house][first_store+1];
		}

		for(int tmp_state = 1; tmp_state < state; tmp_state++){
			for(int last_store = 0; last_store < N; last_store++){
				if(TSP[tmp_state][last_store] == BIG_NUM)continue;

				//次の店へ
				for(int next_store = 0; next_store < N; next_store++){
					if(!is_visit_store[next_store])continue;
					if(tmp_state & (1 << next_store))continue; //訪問済ならSKIP

					next_state = tmp_state+POW[next_store];
					next_cost = TSP[tmp_state][last_store]+min_dist[last_store+1][next_store+1]; //★グラフは1オリジン
					TSP[next_state][next_store] = min(TSP[next_state][next_store],next_cost);
				}
			}
		}

		tmp_dist = BIG_NUM;
		for(int last_store = 0; last_store < N; last_store++){
			if(!is_visit_store[last_store])continue;

			tmp_dist = min(tmp_dist,TSP[state][last_store]+min_dist[my_house][last_store+1]);
		}

		if(ans_cost == tmp_cost){

			ans_dist = min(ans_dist,tmp_dist);

		}else if(ans_cost > tmp_cost){
			ans_cost = tmp_cost;
			ans_dist = tmp_dist;
		}
	}

	if(ans_dist == BIG_NUM){
		printf("impossible\n");
	}else{
		printf("%d %d\n",ans_cost,ans_dist);
	}
}



int main(){

	for(int i = 0; i < 17; i++)POW[i] = pow(2,i);

	while(true){
		scanf("%d",&N);
		if(N == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3308
final_rank: 10

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

typedef pair<int, int> P; // <val, dist>
P dp[11][1 << 15];

struct S {
	int v, buy;
	P d;

	bool operator <(const S& x) const {
		return d > x.d;
	}
};

P rec(S s) {
	return dp[s.v][s.buy];
}

void save(S s) {
	dp[s.v][s.buy] = s.d;
}

struct edge {
	int to, d;
};

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

	int N, Q, M;
	while(cin >> N, N) {
		map<string, int> store[10];
		for(int i = 0; i < N; i++) {
			int k;
			cin >> k;
			for(int j = 0; j < k; j++) {
				string name;
				int val;
				cin >> name >> val;
				store[i][name] = val;
			}
		}
		cin >> Q;
		vector<string> need(Q);
		for(int i = 0; i < Q; i++) {
			cin >> need[i];
		}
		cin >> M;
		vector<edge> G[11];
		for(int i = 0; i < M; i++) {
			int a, b, d;
			cin >> a >> b >> d;
			a--, b--;
			if(a == -1) a = N;
			if(b == -1) b = N;
			G[a].push_back({ b, d });
			G[b].push_back({ a, d });
		}

		priority_queue<S> q;
		S s = { N, 0, { 0, 0 } };
		q.push(s);
		const int INF = 1 << 25;
		fill((P*)begin(dp), (P*)end(dp), P{ INF, INF });
		save(s);

		while(q.size()) {
			s = q.top();
			q.pop();
			if(rec(s) < s.d) continue;
			if(s.v != N) {
				for(int i = 0; i < Q; i++) {
					if(s.buy >> i & 1) continue;
					if(store[s.v].count(need[i]) == 0) continue;
					S ns = s;
					ns.buy |= 1 << i;
					ns.d.first += store[s.v][need[i]];
					if(rec(ns) > ns.d) {
						save(ns);
						q.push(ns);
					}
				}
			}

			for(auto e : G[s.v]) {
				S ns = s;
				ns.v = e.to;
				ns.d.second += e.d;
				if(rec(ns) > ns.d) {
					save(ns);
					q.push(ns);
				}
			}
		}

		P ans = dp[N][(1 << Q) - 1];
		if(ans.first == INF) {
			cout << "impossible" << endl;
		}
		else {
			cout << ans.first << " " << ans.second << endl;
		}
	}
}
accuracy: 1
time_ms: 190
memory_kb: 6708
final_rank: 17

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

struct shop {
	int id;
	vector<int>prices;
};
struct Edge {
	int from;
	int to;
	int cost;
};
struct aa {
	int now;
	bitset<11>came;
	int cost;
};

class Compare {
public:
	bool operator()(const aa&l, const aa&r) {
		return l.cost > r.cost;
	}
};
int N, Q;
int solve(const vector<vector<Edge>>&edges, const bitset<11>&fst_came) {
	vector<vector<int>>memo(N + 1, vector<int>(1 << (N + 1), 1e9));
	priority_queue<aa, vector<aa>, Compare>que;
	que.push(aa{ 0,fst_came,0 });
	while (!que.empty()) {
		aa atop(que.top());
		que.pop();
		if (atop.now == 0 && atop.came.count() == N + 1)return atop.cost;
		else {
			for (auto e : edges[atop.now]) {
				bitset<11>nextcame(atop.came);
				nextcame[e.to] = true;
				const int nextcost = atop.cost + e.cost;
				if (memo[e.to][nextcame.to_ulong()] > nextcost) {
					memo[e.to][nextcame.to_ulong()] = nextcost;
					que.push(aa{ e.to,nextcame,nextcost });
				}
			}
		}
	}
	return 1e9;
}

int main() {
	while (1) { cin >> N;
		if (!N)break;
		vector<shop>shops;
		{
			map<string, int>mp;
			int num = 0;
			vector<vector<int>>sells(N,vector<int>(2000,1e7));
			for (int i = 0; i < N; ++i) {
				int k; cin >> k;
				shop ash;
				ash.id = i;
				for (int j = 0; j < k; ++j) {
					string st; cin >> st;
					int price; cin >> price;
					if (mp.find(st) == mp.end())mp[st] = num++;
					sells[i][mp[st]] = min(sells[i][mp[st]],price);
				}
			}
			 cin >> Q;
			vector<int>needs(Q);
			for (int i = 0; i < Q; ++i) {
				string st; cin >> st;
				if (mp.find(st) == mp.end())mp[st] = num++;
				needs[i] = mp[st];
			}
			for (int i = 0; i < N; ++i) {
				shop sh;
				sh.id = i;
				for (int j = 0; j < Q; ++j) {
					sh.prices.push_back(sells[i][needs[j]]);
				}
				shops.push_back(sh);
			}
		}
		vector<vector<Edge>>edges(N+1);
		{
			int M; cin >> M;
			for (int i = 0; i < M; ++i) {
				int s, t, d; cin >> s >> t >> d;
				edges[s].push_back(Edge{ s,t,d });
				edges[t].push_back(Edge{ t,s,d });
			}
		}
		pair<int, int>ans(1e7,1e8);
		for (int b = 0; b < (1 << N); ++b) {
			bitset<10>bs(b);
			int price_sum = 0;
			int aprice = 1e8;
			for (int j = 0; j < Q; ++j) {
				int aprice = 1e8;
				for (int i = 0; i < N; ++i) {
					if (bs[i])aprice = min(aprice, shops[i].prices[j]);
				}
				price_sum += aprice;
			}
			if (ans.first < price_sum)continue;
			else {
				bitset<11>came;
				came[0] = true;
				for (int i = 0; i < N; ++i) {
					if (!bs[i])came[i + 1] = true;
				}
				int cost = solve(edges, came);
				if (cost > 5e8)continue;
				else {
					ans = min(ans, make_pair(price_sum, cost));
				}
			}
		}
		if (ans.first > 6e6) {
			cout << "impossible" << endl;
		}
		else {
			cout << ans.first << " " << ans.second << endl;
		}
		
	}
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3276
final_rank: 9

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

using namespace std;

const int INF = 1 << 29;

int main()
{
  int N, Q, M;
  int graph[11][11];
  int dp[1 << 11][11];

  while(cin >> N, N) {

    vector< map< string, int > > value(N);
    for(int i = 0; i < N; i++) {
      int k;
      cin >> k;
      while(k--) {
        string name;
        int v;
        cin >> name >> v;
        value[i][name] = v;
      }
    }

    cin >> Q;
    vector< string > need(Q);
    for(int i = 0; i < Q; i++) {
      cin >> need[i];
    }

    cin >> M;
    fill_n(*graph, 11 * 11, INF);
    for(int i = 0; i < M; i++) {
      int s, t, d;
      cin >> s >> t >> d;
      graph[s][t] = graph[t][s] = d;
    }

    ++N;
    for(int k = 0; k < N; k++) {
      for(int i = 0; i < N; i++) {
        for(int j = 0; j < N; j++) {
          graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j]);
        }
      }
    }

    fill_n(*dp, 11 * (1 << 11), INF);
    dp[0][0] = 0;
    for(int i = 0; i < (1 << N); i++) {
      for(int j = 0; j < N; j++) {
        if(dp[i][j] == INF) continue;
        for(int k = 0; k < N; k++) {
          if((i >> k) & 1) continue;
          dp[i | (1 << k)][k] = min(dp[i | (1 << k)][k], dp[i][j] + graph[j][k]);
        }
      }
    }

    pair< int, int > ret(INF, INF);
    for(int i = 0; i < (1 << N); i++) {
      vector< int > vv(Q, INF);
      for(int j = 1; j < N; j++) {
        if((i >> j) & 1) {
          for(int k = 0; k < Q; k++) {
            if(value[j - 1].count(need[k])) {
              vv[k] = min(vv[k], value[j - 1][need[k]]);
            }
          }
        }
      }
      if(count(begin(vv), end(vv), INF) > 0) continue;
      ret = min(ret, {accumulate(begin(vv), end(vv), 0), dp[i][0]});
    }

    if(ret.first == INF) cout << "impossible" << endl;
    else cout << ret.first << " " << ret.second << endl;
  }
}
accuracy: 1
time_ms: 20
memory_kb: 3140
final_rank: 6

code_snippet: #include <bits/stdc++.h>
 
using namespace std;
 
#define MAX_N 10
#define INF 1e9
typedef pair<int,int> pii;
typedef pair<string,int> psi;
 
struct Edge{
    int to,dist;
    Edge(int t,int d) : to(t),dist(d) {}
};
 
struct State{
    int cost,dist,v,S;
    State(int c,int d,int v,int S) 
	: cost(c),dist(d),v(v),S(S) {}
    bool operator < (const State &s)const{
	if(cost != s.cost){
	    return cost > s.cost;
	}else{
	    return dist > s.dist;
	}
    }
};
 
int V,E,K[MAX_N],q;
string shopping_list[15];
vector<psi> items[MAX_N];
vector<Edge> G[MAX_N+1];
 
void solve(){
    priority_queue<State> Q;
    Q.push(State(0,0,0,0));
    pii d[MAX_N+1][1<<15];
    for(int i = 0 ; i <= V ; i++){
	for(int j = 0 ; j < (1<<q) ; j++){
	    d[i][j] = pii(INF,INF);
	}
    }
    d[0][0] = pii(0,0);
   
    while(!Q.empty()){
	State s = Q.top(); Q.pop();
	int v = s.v,S = s.S;
	if(d[v][S] < pii(s.cost,s.dist)) continue;
	if(v == 0 && S == (1<<q)-1){
	    cout << s.cost << " " << s.dist << endl;
	    return;
	}   
	for(int i = 0 ; i < (int)G[v].size() ; i++){
	    Edge e = G[v][i];
	    pii next = pii(d[v][S].first,d[v][S].second+e.dist);
	    if(next < d[e.to][S]){
		d[e.to][S] = next;
		Q.push(State(d[e.to][S].first,d[e.to][S].second,e.to,S));
	    }
	    if(v == 0) continue;
	    for(int j = 0 ; j < q ; j++){
		if((S >> j) & 1) continue;
		for(int k = 0 ; k < K[v-1] ; k++){
		    if(shopping_list[j] == items[v-1][k].first){
			pii next = pii(s.cost + items[v-1][k].second,
				       s.dist + e.dist);
			int nS = S|(1<<j);
			if(next < d[e.to][nS]){
			    d[e.to][nS] = next;
			    Q.push(State(d[e.to][nS].first,d[e.to][nS].second,e.to,nS));
			}
			next.second -= e.dist;
			if(next < d[v][nS]){
			    d[v][nS] = next;
			    Q.push(State(d[v][nS].first,d[v][nS].second,v,nS));
			}
		    }
		}
	    }
	}
    }
    cout << "impossible" << endl;
}
 
int main(){
    while(cin >> V, V){
	string name;
	int value,a,b,d;
	for(int i = 0 ; i <= V ; i++){
	    G[i].clear();
	}
	for(int i = 0 ; i < V ; i++){
	    cin >> K[i];
	    items[i].clear();
	    for(int j = 0 ; j < K[i] ; j++){
		cin >> name >> value;
		items[i].push_back(psi(name,value));
	    }
	}
	cin >> q;
	for(int i = 0 ; i < q ; i++){
	    cin >> shopping_list[i];
	}
	cin >> E;
	for(int i = 0 ; i < E ; i++){
	    cin >> a >> b >> d;
	    G[a].push_back(Edge(b,d));
	    G[b].push_back(Edge(a,d));
	}
	solve();
    }
    return 0;
}
accuracy: 1
time_ms: 350
memory_kb: 7736
final_rank: 20

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

#define for_(i,a,b) for(int i=a;i<b;++i)
#define size_of(a) (int)a.size()
#define minit(a,b) memset(a,b,sizeof(a))

typedef pair< int, int > pii;

const int iINF = (int)1e9;

struct Edge {
	int t, d, c, s;
	Edge(int _t, int _d, int _c, int _s) : t(_t), d(_d), c(_c), s(_s) {}

	bool operator > (const Edge& a) const {
		return (this->c == a.c) ? this->d > a.d : this->c > a.c;
	}
};

int n, q, m;
vector< map< string, int > > store;
string need[15];

vector< vector< Edge > > edges;

pii cost[1 << 16][11];

void solve() {
	for_(i,0,1<<16) for_(j,0,11) cost[i][j] = pii(iINF, iINF);
	
	priority_queue< Edge, vector< Edge >, greater< Edge > > que;
	que.push(Edge(0, 0, 0, 0));
	cost[0][0] = pii(0, 0);
	
	while (!que.empty()) {
		Edge e = que.top(); que.pop();
		
		if (cost[e.s][e.t] < pii(e.c, e.d)) continue;
		
		if (e.t > 0) {
			for_(i,0,q) {
				if (e.s >> i & 1) continue;
				if (store[e.t - 1].find(need[i]) == store[e.t - 1].end()) continue;
				
				int val = store[e.t - 1][need[i]];
				int ss = e.s | (1 << i);
				
				if (cost[ss][e.t] > pii(e.c + val, e.d)) {
					cost[ss][e.t] = pii(e.c + val, e.d);
					que.push(Edge(e.t, e.d, e.c + val, ss));
				}
			}
		}
		
		int e_size = size_of(edges[e.t]);
		for_(i,0,e_size) {
			Edge ei = edges[e.t][i];
			
			if (cost[e.s][ei.t] > pii(e.c, e.d + ei.d)) {
				cost[e.s][ei.t] = pii(e.c, e.d + ei.d);
				que.push(Edge(ei.t, e.d + ei.d, e.c, e.s));
			}
		}
	}
	
	pii ans = cost[(1 << q) - 1][0];
	if (ans.first == iINF && ans.second == iINF) cout << "impossible" << endl;
	else cout << ans.first << " " << ans.second << endl;
}

int main() {
	while (cin >> n, n) {
		store.assign(n, map< string, int >());
		
		for_(i,0,n) {
			int k; cin >> k;
			
			for_(j,0,k) {
				string name; int val;
				cin >> name >> val;
				store[i][name] = val;
			}
		}
		
		cin >> q;
		for_(i,0,q) cin >> need[i];
		
		cin >> m;
		edges.assign(n + 1, vector< Edge >());
		
		for_(i,0,m) {
			int s, t, d; cin >> s >> t >> d;
			edges[s].push_back(Edge(t, d, 0, 0));
			edges[t].push_back(Edge(s, d, 0, 0));
		}
		
		solve();
	}
		
	return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 7772
final_rank: 18

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

#define repi(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,n) repi(i,0,n)
#define all(c) begin(c),end(c)

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<string> vs;

constexpr int INF=1e9;

int main()
{
	for(int n;cin>>n && n;){
		vector<map<string,int>> ss(n);
		rep(i,n){
			int k; cin>>k;
			rep(j,k){
				string name; int value; cin>>name>>value;
				ss[i][name]=value;
			}
		}
		int q; cin>>q;
		vs ns(q);
		rep(i,q) cin>>ns[i];
		int m; cin>>m;
		vvi d(n+1,vi(n+1,INF));
		rep(i,n+1) d[i][i]=0;
		rep(i,m){
			int u,v,w; cin>>u>>v>>w;
			(u+=n)%=n+1; (v+=n)%=n+1;
			d[u][v]=d[v][u]=w;
		}
		
		rep(k,n+1) rep(i,n+1) rep(j,n+1)
			d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
		
		vvi dp(1<<n+1,vi(n+1,INF));
		rep(i,n) dp[1<<i][i]=d[n][i];
		rep(i,1<<n+1) rep(j,n+1) if(i>>j&1) rep(k,n+1) if(!(i>>k&1))
			dp[i|1<<k][k]=min(dp[i|1<<k][k],dp[i][j]+d[j][k]);
		
		tuple<int,int> res(INF,INF);
		rep(i,1<<n){
			vi ps(q,INF);
			rep(j,n) if(i>>j&1)
				rep(k,q) if(ss[j].count(ns[k]))
					ps[k]=min(ps[k],ss[j][ns[k]]);
			if(count(all(ps),INF)) continue;
			res=min(res,make_tuple(accumulate(all(ps),0),dp[i|1<<n][n]));
		}
		
		if(res==make_tuple(INF,INF))
			cout<<"impossible"<<endl;
		else
			cout<<get<0>(res)<<' '<<get<1>(res)<<endl;
	}
}
accuracy: 1
time_ms: 20
memory_kb: 1428
final_rank: 3

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

#define dump(...) cout<<"# "<<#__VA_ARGS__<<'='<<(__VA_ARGS__)<<endl
#define repi(i,a,b) for(int i=int(a);i<int(b);i++)
#define peri(i,a,b) for(int i=int(b);i-->int(a);)
#define rep(i,n) repi(i,0,n)
#define per(i,n) peri(i,0,n)
#define all(c) begin(c),end(c)
#define mp make_pair
#define mt make_tuple

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;

template<typename T1,typename T2>
ostream& operator<<(ostream& os,const pair<T1,T2>& p){
	return os<<'('<<p.first<<','<<p.second<<')';
}

template<typename Tuple>
void print_tuple(ostream&,const Tuple&){}
template<typename Car,typename... Cdr,typename Tuple>
void print_tuple(ostream& os,const Tuple& t){
	print_tuple<Cdr...>(os,t);
	os<<(sizeof...(Cdr)?",":"")<<get<sizeof...(Cdr)>(t);
}
template<typename... Args>
ostream& operator<<(ostream& os,const tuple<Args...>& t){
	print_tuple<Args...>(os<<'(',t);
	return os<<')';
}

template<typename Ch,typename Tr,typename C,typename=decltype(begin(C()))>
basic_ostream<Ch,Tr>& operator<<(basic_ostream<Ch,Tr>& os,const C& c){
	os<<'[';
	for(auto i=begin(c);i!=end(c);++i)
		os<<(i==begin(c)?"":" ")<<*i;
	return os<<']';
}

constexpr int INF=1e9;
constexpr int MOD=1e9+7;
constexpr double EPS=1e-9;

int main()
{
	for(int n;cin>>n && n;){
		vector<map<string,int>> ss(n);
		rep(i,n){
			int k; cin>>k;
			rep(j,k){
				string name; int value; cin>>name>>value;
				ss[i][name]=value;
			}
		}
		int q; cin>>q;
		vs ns(q);
		rep(i,q) cin>>ns[i];
		int m; cin>>m;
		vvi d(n+1,vi(n+1,INF));
		rep(i,n+1) d[i][i]=0;
		rep(i,m){
			int u,v,w; cin>>u>>v>>w;
			(u+=n)%=n+1; (v+=n)%=n+1;
			d[u][v]=d[v][u]=w;
		}
		
		rep(k,n+1) rep(i,n+1) rep(j,n+1)
			d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
		
		vvi dp(1<<(n+1),vi(n+1,INF));
		rep(i,n) dp[1<<i][i]=d[n][i];
		rep(i,1<<(n+1)) rep(j,n+1) if(i>>j&1) rep(k,n+1) if(!(i>>k&1))
			dp[i|1<<k][k]=min(dp[i|1<<k][k],dp[i][j]+d[j][k]);
		
		pii res(INF,INF);
		rep(i,1<<n){
			vi ps(q,INF);
			rep(j,n) if(i>>j&1)
				rep(k,q) if(ss[j].count(ns[k]))
					ps[k]=min(ps[k],ss[j][ns[k]]);
			if(count(all(ps),INF)) continue;
			res=min(res,mp(accumulate(all(ps),0),dp[i|1<<n][n]));
		}
		
		if(res==mp(INF,INF))
			puts("impossible");
		else
			printf("%d %d\n",res.first,res.second);
	}
}
accuracy: 1
time_ms: 20
memory_kb: 1432
final_rank: 4

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

using namespace std;

#define MAX_N 10
#define INF 1e9
typedef pair<int,int> pii;
typedef pair<string,int> psi;

struct Edge{
  int to,dist;
  Edge(int t,int d) : to(t),dist(d) {}
};

struct State{
  int cost,dist,v,S;
  State(int c,int d,int v,int S) 
    : cost(c),dist(d),v(v),S(S) {}
  bool operator < (const State &s)const{
    if(cost != s.cost){
      return cost > s.cost;
    }else{
      return dist > s.dist;
    }
  }
};

int V,E,K[MAX_N],q;
string shopping_list[15];
vector<psi> items[MAX_N];
vector<Edge> G[MAX_N+1];

void solve(){
  priority_queue<State> Q;
  Q.push(State(0,0,0,0));
  pii d[MAX_N+1][1<<15];
  for(int i = 0 ; i <= V ; i++){
    for(int j = 0 ; j < (1<<q) ; j++){
      d[i][j] = pii(INF,INF);
    }
  }
  d[0][0] = pii(0,0);
  
  while(!Q.empty()){
    State s = Q.top(); Q.pop();
    int v = s.v,S = s.S;
    if(d[v][S] < pii(s.cost,s.dist)) continue;
    if(v == 0 && S == (1<<q)-1){
      cout << s.cost << " " << s.dist << endl;
      return;
    }   
    for(int i = 0 ; i < (int)G[v].size() ; i++){
      Edge e = G[v][i];
      pii next = pii(d[v][S].first,d[v][S].second+e.dist);
      if(next < d[e.to][S]){
        d[e.to][S] = next;
        Q.push(State(d[e.to][S].first,d[e.to][S].second,e.to,S));
      }
      if(v == 0) continue;
      for(int j = 0 ; j < q ; j++){
        if((S >> j) & 1) continue;
        for(int k = 0 ; k < K[v-1] ; k++){
          if(shopping_list[j] == items[v-1][k].first){
            pii next = pii(s.cost + items[v-1][k].second,
                           s.dist + e.dist);
            int nS = S|(1<<j);
            if(next < d[e.to][nS]){
              d[e.to][nS] = next;
              Q.push(State(d[e.to][nS].first,d[e.to][nS].second,e.to,nS));
            }
            next.second -= e.dist;
            if(next < d[v][nS]){
              d[v][nS] = next;
              Q.push(State(d[v][nS].first,d[v][nS].second,v,nS));
            }
          }
        }
      }
    }
  }
  cout << "impossible" << endl;
}

int main(){
  while(cin >> V, V){
    string name;
    int value,a,b,d;
    for(int i = 0 ; i <= V ; i++){
      G[i].clear();
    }
    for(int i = 0 ; i < V ; i++){
      cin >> K[i];
      items[i].clear();
      for(int j = 0 ; j < K[i] ; j++){
        cin >> name >> value;
        items[i].push_back(psi(name,value));
      }
    }
    cin >> q;
    for(int i = 0 ; i < q ; i++){
      cin >> shopping_list[i];
    }
    cin >> E;
    for(int i = 0 ; i < E ; i++){
      cin >> a >> b >> d;
      G[a].push_back(Edge(b,d));
      G[b].push_back(Edge(a,d));
    }
    solve();
  }
  return 0;
}
accuracy: 1
time_ms: 410
memory_kb: 5988
final_rank: 19

code_snippet: #include <cstdlib>
#include <iostream>
#include <numeric>
#include <unordered_map>
#include <vector>
using namespace std;

template<class T> inline void chmin(T &a, const T &b) { if(a > b) a = b; }

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);

	constexpr int INF = (1 << 25);

	for(int n; cin >> n && n;) {
		vector<vector<pair<string, int>>> supers(n);
		for(int i = 0; i < n; ++i) {
			int k;
			cin >> k;

			supers[i].reserve(k);
			while(k--) {
				string name;
				int value;
				cin >> name >> value;
				supers[i].emplace_back(name, value);
			}
		}

		int q;
		cin >> q;
		unordered_map<string, int> conv;

		for(int i = 0; i < q; ++i) {
			string name;
			cin >> name;
			conv.insert({name, i});
		}

		vector<vector<int>> costs(n, vector<int>(q, INF));
		for(int i = 0; i < n; ++i) {
			for(const auto &e : supers[i]) {
				if(conv.count(e.first)) {
					costs[i][conv[e.first]] = e.second;
				}
			}
		}

		int m;
		cin >> m;

		vector<vector<int>> mat(n + 1, vector<int>(n + 1, INF));
		while(m--) {
			int s, t, d;
			cin >> s >> t >> d;
			s = (s + n) % (n + 1);
			t = (t + n) % (n + 1);
			mat[s][t] = mat[t][s] = d;
		}

		for(int i = 0; i <= n; ++i) mat[i][i] = 0;
		for(int k = 0; k <= n; ++k) {
			for(int i = 0; i <= n; ++i) {
				for(int j = 0; j <= n; ++j) {
					chmin(mat[i][j], mat[i][k] + mat[k][j]);
				}
			}
		}

		int min_cost = INF, min_dist = INF;
		for(int i = 0; i < (1 << n); ++i) {
			vector<int> c(q, INF);
			for(int j = 0; j < n; ++j) {
				if(!(i & (1 << j))) continue;
				for(int k = 0; k < q; ++k) {
					chmin(c[k], costs[j][k]);
				}
			}

			const int sum_cost = accumulate(c.begin(), c.end(), 0);
			if(sum_cost <= min_cost) {
				if(sum_cost < min_cost) {
					min_cost = sum_cost;
					min_dist = INF;
				}

				vector<vector<int>> dp(n, vector<int>(i + 1, INF));
				for(int j = 0; j < n; ++j) {
					if(i & (1 << j)) {
						dp[j][1 << j] = mat[n][j];
					}
				}

				for(int k = 1; k < i; ++k) {
					if(!(i & k) || (~i & k)) continue;
					for(int j = 0; j < n; ++j) {
						if(dp[j][k] == INF) continue;
						for(int l = 0; l < n; ++l) {
							const int next_visited = (k | (1 << l));
							if(k == next_visited || (~i & next_visited)) continue;
							chmin(dp[l][next_visited], dp[j][k] + mat[j][l]);
						}
					}
				}

				int sum_dist = INF;
				for(int j = 0; j < n; ++j) {
					chmin(sum_dist, dp[j][i] + mat[j][n]);
				}
				chmin(min_dist, sum_dist);
			}
		}

		if(min_cost == INF) {
			cout << "impossible" << endl;
		}
		else {
			cout << min_cost << " " << min_dist << endl;
		}
	}

	return EXIT_SUCCESS;
}
accuracy: 1
time_ms: 20
memory_kb: 1308
final_rank: 2

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
#include<map>

using namespace std;

const int INF = (1<<28);
const int MAX = 16;

typedef pair<string,int> P;
typedef pair<int,int> Pii;

struct edge{int to, cost;};
struct State{
  Pii t;
  int pos, need;
  bool operator < (const State& st) const {
    return t > st.t;
  }
};

map<string, int> idx;
int val[MAX];
vector<edge> E[MAX];
Pii T[MAX][(1<<MAX)];
int shop[MAX];
int N,wanted;

void init(){
  fill(T[0], T[0]+MAX*(1<<MAX), Pii(INF,INF));
  idx.clear();
  memset(val, -1, sizeof(val));
  wanted = 0;
  for(int i = 0; i < MAX; i++){
    E[i].clear();
    shop[i] = 0;
  }
}

void input(){
  vector<P> v[N];
  int cnt = 0;
  for(int i = 0; i < N; i++){
    int q;
    cin >> q;
    v[i].resize(q);
    for(int j = 0; j < q; j++){
      cin >> v[i][j].first >> v[i][j].second;
      if(!idx.count(v[i][j].first)) idx[v[i][j].first] = cnt++; 
      if(val[idx[v[i][j].first]] == -1) val[idx[v[i][j].first]] = v[i][j].second;
      else val[idx[v[i][j].first]] = min(val[idx[v[i][j].first]], v[i][j].second);
    }
  }


  for(int i = 0; i < N; i++)
    for(int j = 0; j < (int)v[i].size(); j++)
      if(val[idx[v[i][j].first]] == v[i][j].second) shop[i+1] |= (1<<idx[v[i][j].first]);
      
  int q;
  cin >> q;
  while(q--){
    string name;
    cin >> name;
    if(!idx.count(name)) idx[name] = cnt++;
    wanted |= (1<<idx[name]);
  }


  int m;
  cin >> m;
  while(m--){
    int a,b,c;
    cin >> a >> b >> c;
    E[a].push_back((edge){b,c});
    E[b].push_back((edge){a,c});
  }
}

void solve(){

  T[0][wanted] = Pii(0,0);
  priority_queue<State> Q;
  Q.push((State){Pii(0,0),0,wanted});

  while(!Q.empty()){
    const State st = Q.top();
    Q.pop();

    if(T[st.pos][st.need] < st.t) continue;

    for(int i = 0; i < (int)E[st.pos].size(); i++){
      State nex = st;
      nex.t.first = st.t.first;
      nex.t.second += E[st.pos][i].cost;
      nex.pos = E[st.pos][i].to;
      nex.need = st.need;

      int canbuy = shop[nex.pos]&nex.need;
      for(int i = 0; i < MAX; i++)
	if(canbuy & (1<<i)){
	  nex.need -= (1<<i);
	  nex.t.first += val[i];
	}
      
      if(T[nex.pos][nex.need] > nex.t){
	T[nex.pos][nex.need] = nex.t;
	Q.push(nex);
      }
    }
  }
  
  if(T[0][0].first == INF) cout << "impossible" << endl;
  else cout << T[0][0].first << " " << T[0][0].second << endl;
}

int main(){
  
  while(cin >> N && N){
    init();
    input();
    solve();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 9448
final_rank: 16

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

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

using namespace std;

const int INF=1<<29;

int main(){
	for(int n;cin>>n,n;){
		vector<string> name[10];
		vector<int> price[10];
		rep(i,n){
			int m; cin>>m;
			name[i].resize(m);
			price[i].resize(m);
			rep(j,m) cin>>name[i][j]>>price[i][j];
		}

		int q; cin>>q;
		string want[15];
		rep(i,q) cin>>want[i];

		int m; cin>>m;
		int d[11][11];
		rep(u,n+1) rep(v,n+1) d[u][v]=(u==v?0:INF);
		rep(i,m){
			int u,v,dd; cin>>u>>v>>dd;
			d[u][v]=d[v][u]=min(d[u][v],dd);
		}
		rep(k,n+1) rep(i,n+1) rep(j,n+1) d[i][j]=min(d[i][j],d[i][k]+d[k][j]);

		int p[10][15];
		rep(i,n) rep(j,q) p[i][j]=INF;
		rep(i,n) rep(j,name[i].size()) rep(k,q) if(name[i][j]==want[k]) p[i][k]=min(p[i][k],price[i][j]);
		int p_ans=0;
		// 一番安い店のみ興味がある
		rep(j,q){
			int p_min=INF;
			rep(i,n) p_min=min(p_min,p[i][j]);
			rep(i,n) if(p[i][j]>p_min) p[i][j]=INF;
			p_ans=min(p_ans+p_min,INF);
		}
		if(p_ans==INF){ cout<<"impossible"<<endl; continue; }

		if(q==0){ cout<<"0 0"<<endl; continue; }

		// TSP
		int mask[11]={};
		rep(i,n) rep(j,q) if(p[i][j]<INF) mask[i+1]|=1<<j;

		int d_ans=INF;
		int perm[10]={1,2,3,4,5,6,7,8,9,10};
		do{
			int S=0,pos=0,d_now=d[0][perm[0]];
			rep(i,n){
				pos=perm[i];
				S|=mask[pos];
				if(S==(1<<q)-1){ d_now+=d[pos][0]; break; }
				d_now+=d[pos][perm[i+1]];
			}
			d_ans=min(d_ans,d_now);
		}while(next_permutation(perm,perm+n));

		cout<<p_ans<<" "<<d_ans<<endl;
	}

	return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 1224
final_rank: 14

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <utility>
#include <map>
#include <queue>
#include <functional>
#include <cstdio>
using namespace std;

typedef pair<int,int> pii;

const int INF = 1e9;


void func(vector<pii> &dp, const vector<pii> &item, int S, int j){
	if( j < item.size() ){
		int x = 1 << item[j].first;
		if( !(x & S) ){
			pii p(dp[S].first + item[j].second, dp[S].second);
			if( dp[x | S] > p){
				dp[x | S] = p;
				func(dp, item, x | S, j + 1);
			}
		}
		
		func(dp, item, S, j + 1);
	}
}


void dijkstra(
	vector<vector<pii> > &dp,
	const vector<vector<pii> > &road,
	int n, int S
){


	typedef pair<pii,int> piii;

	priority_queue<piii,vector<piii>,greater<piii> > pq;
	for(int i = 0; i <= n; ++i){
		if( dp[i][S].first != INF ){
			pq.push( piii(dp[i][S], i) );
		}
	}

	while( !pq.empty() ){
		piii p = pq.top();
		pq.pop();

		int x = p.second;
		if( dp[x][S] != p.first ) continue;

		for(int j = 0; j < road[x].size(); ++j){
			int t = road[x][j].first;
			pii next(p.first.first, p.first.second + road[x][j].second);

			if(dp[t][S] > next){
				dp[t][S] = next;
				pq.push( piii(next, t) );
			}
		}
	}

}


int main(){
	int n;
	while(cin >> n, n != 0){
		vector<vector<string> > name(n + 1);
		vector<vector<int> > value(n + 1);
		string str;
		int v, k;
		
		for(int i = 1; i <= n; ++i){
			cin >> k;
			name[i].reserve(k);
			value[i].reserve(k);

			for(int j = 0; j < k; ++j){
				cin >> str >> v;
				name[i].push_back(str);
				value[i].push_back(v);
			}
		}
		
		int q;
		cin >> q;
		map<string,int> itemtable;
		for(int i = 0; i < q; ++i){
			cin >> str;
			itemtable[str] = i;
		}
		
		vector<vector<pii> > shop(n + 1);
		for(int i = 1; i <= n; ++i){
			for(int j = 0; j < name[i].size(); ++j){
				map<string,int>::iterator it = itemtable.find(name[i][j]);
				if( it != itemtable.end() ){
					shop[i].push_back( pii(it->second, value[i][j]) );
				}
			}
		}
		
		vector<vector<pii> > road(n + 1);
		int m, s, t, d;
		
		cin >> m;
		for(int i = 0; i < m; ++i){
			cin >> s >> t >> d;
			road[s].push_back( pii(t, d) );
			road[t].push_back( pii(s, d) );
		}
		
		int last = 1 << q;
		vector<vector<pii> > dp(n + 1, vector<pii>(last, pii(INF, INF) ) );
		dp[0][0] = pii(0, 0);

		for(int S = 0; S < last; ++S){
			dijkstra(dp, road, n, S);

			for(int i = 1; i <= n; ++i){
				func(dp[i], shop[i], S, 0);
			}
		}
		
		int cost = dp[0].back().first;
		int dist = dp[0].back().second;
		
		if( cost == INF ){
			cout << "impossible\n";
		}
		else{
			cout << cost << ' ' << dist << '\n';
		}
	}
}
accuracy: 1
time_ms: 70
memory_kb: 3644
final_rank: 15

code_snippet: #include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip> 
#include <complex> 
#include <string>
#include <vector> 
#include <list>
#include <deque> 
#include <stack> 
#include <queue> 
#include <set>
#include <map>
#include <bitset>
#include <functional>
#include <utility>
#include <algorithm> 
#include <numeric> 
#include <typeinfo> 
#include <cstdio>
#include <cstdlib> 
#include <cstring>
#include <cmath>
#include <climits> 
#include <ctime>
using namespace std;

typedef pair<string,int> P;
int n,q,m;

vector<P> v[11];
vector<string> name;
map<string,int> sale;
int root[11][11];
const int INF=10000000;
int dpc[11][1<<15];
int dpd[11][1<<15];
int ac;
int ad;

void rec(int x,int bit,int c,int d){
	if(dpc[x][bit]<c)return;
	if(dpc[x][bit]==c && dpd[x][bit]<d)return;
	dpc[x][bit]=c;
	dpd[x][bit]=d;
	int nbit=bit;
	int nc=c;
	for(int i=0;i<v[x].size();i++){
		for(int j=0;j<name.size();j++){
			if(name[j]==v[x][i].first && !(bit >> j & 1) && sale[name[j]]==v[x][i].second){
				nbit |= 1<<j;
				nc+=v[x][i].second;
			}
		}
	}
	if(nbit==(1<<q)-1){
		if(nc<ac || (nc==ac && d+root[0][x]<ad)){
			ac=nc;
			ad=d+root[0][x];
		}
	}else{
		for(int i=1;i<=n;i++){
			int nd=d+root[i][x];
			if(dpc[i][nbit]>nc || (dpc[i][nbit]==nc && dpd[i][nbit]>nd)){
				dpc[i][nbit]=nc;
				dpd[i][nbit]=nd;
				rec(i,nbit,nc,nd);
			}
		}
	}
}


int main(void){
	while(1){
		ac=INF;
		ad=INF;
		bool ch=true;
		for(int i=0;i<=10;i++){
			for(int j=0;j<=10;j++){
				root[i][j]=INF;
			}
			root[i][i]=0;
			v[i].clear();
		}
		for(int i=0;i<=10;i++){
			for(int j=0;j<=(1<<15)-1;j++){
				dpc[i][j]=INF;
				dpd[i][j]=INF;
			}
		}
		name.clear();
		sale.clear();
		cin >> n;
		if(n==0)break;
		for(int i=1;i<=n;i++){
			int k;
			cin >> k;
			for(int j=0;j<k;j++){
				string str;
				int cost;
				cin >> str >> cost;
				v[i].push_back(P(str,cost));
				if(sale[str]==0)sale[str]=cost;
				else sale[str]=min(cost,sale[str]);
			}
		}
		cin >> q;
		for(int i=0;i<q;i++){
			string str;
			cin >> str;
			name.push_back(str);
			if(sale[str]==0)ch=false;
		}
		cin >> m;
		for(int i=0;i<m;i++){
			int s,t,d;
			cin >> s >> t >> d;
			root[s][t]=min(d,root[s][t]);
			root[t][s]=min(d,root[t][s]);
		}
		for(int k=0;k<=n;k++){
			for(int i=0;i<=n;i++){
				for(int j=0;j<=n;j++){
					root[i][j]=min(root[i][j],root[i][k]+root[k][j]);
				}
			}
		}
		if(ch)rec(0,0,0,0);
		if(ac>=INF || ch==false)cout << "impossible" << endl;
		else cout << ac << " " << ad << endl;
	}
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4052
final_rank: 12

code_snippet: #include <iostream>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <cstdio>
#include <queue>
using namespace std;

int main(){
	int n;
	while(cin >> n && n){
		n++;
		vector< pair<string,int> > shop[16];
		for(int i = 1 ; i <= n-1 ; i++){
			int k;
			cin >> k;
			for(int j = 0 ; j < k ; j++){
				string name;
				int value;
				cin >> name >> value;
				shop[i].push_back( make_pair(name,value) );
			}
		}
		set<string> want;
		vector<string> lst;
		int q;
		cin >> q;
		for(int i = 0 ; i < q ; i++){
			string t; cin >> t;
			want.insert(t);
			lst.push_back(t);
		}
		vector< pair<int,int> > con;
		
		for(int i = 0 ; i < (1<<n) ; i++){
			set<string> w = want;
			map<string,int> mini;
			for(int j = 0 ; j < n ; j++){
				if( !(i>>j&1) ) continue;
				for(int k = 0 ; k < shop[j].size() ; k++){
					w.erase(shop[j][k].first);
					if( mini.count(shop[j][k].first) == 0 ) mini[shop[j][k].first] = shop[j][k].second;
					else mini[shop[j][k].first] = min( mini[shop[j][k].first] , shop[j][k].second);
				}
			}
			if( w.size() != 0 ) continue;
			
			int sum = 0;
			for(int j = 0 ; j < q ; j++){
				sum += mini[lst[j]];
			}
			con.push_back(make_pair(sum,i));
		}
		int m;
		cin >> m;
		int wf[11][11] = {};
		for(int i = 0 ; i < n ; i++)
			for(int j = 0 ; j < n ; j++)
				wf[i][j] = 1e9;
		for(int i = 0 ; i < n ; i++)
			wf[i][i] = 0;
		for(int i = 0 ; i < m ; i++){
			int s,t,d;
			cin >> s >> t >> d;
			wf[s][t] = wf[t][s] = min(wf[s][t],d);
		}
		for(int i = 0 ; i < n ; i++)
			for(int j = 0 ; j < n ; j++)
				for(int k = 0 ; k < n ; k++)
					wf[j][k] = min(wf[j][k],wf[j][i]+wf[i][k]);
		int dp[1<<11][11] = {};
		for(int i = 0 ; i < (1<<11) ; i++)
			for(int j = 0 ; j < 11 ; j++)
				dp[i][j] = 1e9;
		dp[1][0] = 0;
		if( con.size() == 0 ){
			cout <<  "impossible" << endl;
		}else{
			sort(con.begin(),con.end());
			for(int i = 0 ; i < (1<<n) ; i++){
				for(int j = 0 ; j < n ; j++){
					if( i >> j & 1 ) {
						for(int k = 0 ; k < n ; k++){
							dp[i|(1<<k)][k] = min(dp[i|(1<<k)][k],dp[i][j]+wf[j][k]);
						}
					}
				}
			}
			int distance = 1e9;
			int firstCost = con[0].first;
			for(int i = 0 ; i < con.size() ; i++){
				if( con[0].first != con[i].first ) break;
				int bit = con[i].second | 1;
				for(int j = 0 ; j < n ; j++){
					distance = min(distance,dp[bit][j]+wf[j][0]);
				}
			}
			cout << firstCost << " " << distance << endl;
			
		}
	}
	
}
accuracy: 1
time_ms: 50
memory_kb: 1352
final_rank: 5

code_snippet: #include<cstdio>
#include<cstring>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
typedef map<string,int>M;
M shop[10];
string name[15];
int INF=0x3f3f3f3f,edge[11][11],n,q;
int minCost,minLength;
void F(int s)
{
	int i,j,k;
	int cost=0,tempCost;
	for(i=0;i<q;++i)
	{
		tempCost=INF;
		for(j=0;j<n;++j)
		{
			if(!(s&(1<<j)))continue;
			M::iterator ite=shop[j].find(name[i]);
			if(ite!=shop[j].end())
			{
				tempCost=min(tempCost,ite->second);
			}
		}
		if(tempCost==INF)return;
		cost+=tempCost;
	}
	if(minCost<cost)return;
	if(minCost>cost)
	{
		minCost=cost;
		minLength=INF;
	}

	s=(s<<1)+1;
	int dp[1<<11][11];
	memset(dp,INF,sizeof(dp));
	dp[1][0]=0;
	for(i=1;i<(1<<(n+1));++i)
	{
		if(i&~s)continue;
		for(j=0;j<n+1;++j)
		{
			for(k=0;k<n+1;++k)
			{
				int&r=dp[i|(1<<k)][k];
				r=min(r,dp[i][j]+edge[j][k]);
			}
		}
	}
	minLength=min(minLength,dp[s][0]);
}
int main()
{
	int i,j,k,v,m,a,b,d;
	char str[256];
	while(scanf("%d",&n),n)
	{
		memset(edge,INF,sizeof(edge));
		minCost=minLength=INF;
		for(i=0;i<n;++i)
		{
			shop[i].clear();
			for(scanf("%d",&k);k--;)scanf("%s%d",str,&v),shop[i][str]=v;
		}
		for(i=!scanf("%d",&q);i<q;++i)
		{
			scanf("%s",str);
			name[i]=str;
		}
		for(scanf("%d",&m);m--;)
		{
			scanf("%d%d%d",&a,&b,&d);
			edge[a][b]=edge[b][a]=d;
		}
		for(k=0;k<n+1;++k)for(i=0;i<n+1;++i)for(j=0;j<n+1;++j)edge[i][j]=min(edge[i][j],edge[i][k]+edge[k][j]);
		for(i=1;i<(1<<n);++i)F(i);
		if(minCost>=INF)puts("impossible");
		else printf("%d %d\n",minCost,minLength);
	}
	return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 936
final_rank: 13

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <queue>
#include <map>
#include <set>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
const int INF = 1<<29;
typedef int Weight;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;
// ツ経ツ路ツつ「ツづァツづ按つ「ツづつォ
const int M = 20;
Weight best[1<<M][M];

Weight shortestHamiltonPath(Matrix w, int s) {
  int n = w.size();
  int N = 1 << n;
  REP(S,N) REP(i,n) best[S][i] = INF;
  best[1<<s][s] = 0;
  REP(S,N) REP(k,n) REP(i,n) if (S&(1<<i))
    REP(j,n)
      best[S|(1<<j)][j] = min(best[S|(1<<j)][j], best[S][i] + w[i][j]);
  Weight res = INF;
  REP(i, n) {
    res = min(res, best[N-1][i] + w[i][s]);
  }
  return res;
}

int main() {
  int n;
  while(cin>>n,n) {
    map<string, int> mp[n];
    map<string, int> mi;
    REP(i, n) {
      int k;
      cin >> k;
      REP(j, k) {
        string s; int v;
        cin >> s >> v;
        mp[i][s] = v;
        if (mi.count(s) == 0) mi[s] = v;
        else if (mi[s] > v) mi[s] = v;
      }
    }
    int q;cin >> q;
    int mask[n];
    memset(mask, 0, sizeof(mask));
    int ans1 = 0;
    bool dame = 0;
    REP(i, q) {
      string s;
      cin >> s;
      if (mi.count(s) == 0) {
        dame = 1;
        continue;
      }
      ans1 += mi[s];
      REP(j, n) {
        if (mp[j][s] == mi[s]) mask[j] |= 1<<i;
      }
    }
    int m;
    cin >> m;
    Matrix g(n+1, Array(n+1, INF));
    REP(i, m) {
      int s, t, d;
      cin >> s >> t >> d;
      g[s][t] = d;
      g[t][s] = d;
    }
    
    if (dame) {
      cout << "impossible" << endl;
      continue;
    }
    // REP(i, n+1) {
    //   REP(j, n+1) {
    //     cout << g[i][j] << " ";
    //   }
    //   cout << endl;
    // }cout << endl;
    int res = INF;
    REP(S, 1<<n) {
      int buy = 0;
      int num = 0;
      REP(i, n) {
        if (S>>i&1) {
          buy |= mask[i];
          num++;
        }
      }
      if (buy != (1<<q)-1) continue;
      Matrix sub(num+1, Array(num+1, INF));
      int y = 0;
      REP(i, n) {
        if (!(S>>i&1)) continue;
        sub[y+1][0] = g[i+1][0];
        sub[0][y+1] = g[0][i+1];
        int x = 0;
        REP(j, n) {
          if (!(S>>j&1)) continue;
          sub[y+1][x+1] = g[i+1][j+1];
          x++;
        }
        y++;
      }
      
      // REP(i, num+1) {
      //   REP(j, num+1) {
      //     cout << sub[i][j] << " ";
      //   }
      //   cout << endl;
      // }cout << endl;
      res = min(res, shortestHamiltonPath(sub, 0));
    }
    if (res == INF) {
      cout << "impossible" << endl;
    } else {
      cout << ans1 << " " << res << endl;
    }
  }
}
accuracy: 1
time_ms: 110
memory_kb: 1100
final_rank: 8

code_snippet: #include<iostream>
#include<vector>
#include<map>
#include<numeric>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
const int N = 11;
const int inf = (1<<20);

template <class T> int getindex(T &a,map<T,int> & M){
  int index = M.size();
  if (M.find(a) == M.end())M[a]=index;
  return M[a];
}

int g[N][N];
int dp[(1<<N)][N];
void tsp(int n){
  rep(k,n)rep(i,n)rep(j,n)g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
  rep(i,(1<<n))rep(j,n)dp[i][j]=inf;
  dp[1<<0][0]=0;
  rep(i,(1<<n)){
    rep(j,n){//visited
      if (((1<<j)&i) == 0)continue;
      rep(k,n){//unvisited
	if ((1<<k)&i)continue;
	int next=(1<<k)|i;
	dp[next][k]=min(dp[next][k],dp[i][j]+g[j][k]);
      }
    }
  }
}

void solve(int n,map<int,int> *c,vector<int> &req){
  int ac=inf,aw=inf;
  rep(i,(1<<n)){
    if ((1&i) == 0)continue;
    int tc=inf,tw=inf;
    vector<int> mini(req.size(),inf);
    rep(j,n){
      if (((1<<j)&i) == 0)continue;
      tw=min(tw,dp[i][j]+g[j][0]);
      rep(k,(int)req.size()){
	if (c[j].find(req[k]) != c[j].end())mini[k]=min(mini[k],c[j][req[k]]);
      }
      tc = accumulate(mini.begin(),mini.end(),0);
    }
    if (tc < ac || (tc == ac && tw < aw))ac=tc,aw=tw;
  }
  if (ac == inf)cout <<"impossible"<<endl;
  else cout << ac <<" " << aw << endl;
}

main(){
  int n;
  while(cin>>n && n){
    rep(i,n+1){rep(j,n+1)g[i][j]=inf;g[i][i]=0;}
    map<string,int> M;
    map<int,int> c[n+1];
    rep(i,n){
      int num;cin>>num;
      rep(j,num){
	string name;int cost,ind;
	cin>>name>>cost;
	ind=getindex(name,M);
	c[i+1][ind]=cost;
      }
    }

    int req;
    cin>>req;
    vector<int> in(req);
    rep(i,req){
      string tmp;
      cin>>tmp;
      in[i]=getindex(tmp,M);
    }
    
    int m;
    cin>>m;
    rep(i,m){
      int f,t,c;cin>>f>>t>>c;
      g[f][t]=g[t][f]=c;
    }
    tsp(n+1);

    solve(n+1,c,in);
  }
}
accuracy: 1
time_ms: 10
memory_kb: 0
final_rank: 1