Problem:
Problem D:
International Party
Isaac H. Ives is attending an international student party (maybe for girl-hunting). Students there enjoy
talking in groups with excellent foods and drinks. However, since students come to the party from all
over the world, groups may not have a language spoken by all students of the group. In such groups,
some student(s) need to work as interpreters, but intervals caused by interpretation make their talking
less exciting.
Needless to say, students want exciting talks. To have talking exciting as much as possible, Isaac proposed
the following rule: the number of languages used in talking should be as little as possible, and not exceed
five. Many students agreed with his proposal, but it is not easy for them to find languages each student
should speak. So he calls you for help.
Your task is to write a program that shows the minimum set of languages to make talking possible, given
lists of languages each student speaks.
Input
The input consists of a series of data sets.
The first line of each data set contains two integers
N
(1 ≤
N
≤ 30) and
M
(2 ≤
M
≤ 20) separated
by a blank, which represent the numbers of languages and students respectively. The following
N
lines
contain language names, one name per line. The following
M
lines describe students in the group. The
i
-th line consists of an integer
K
i
that indicates the number of languages the
i
-th student speaks, and
K
i
language names separated by a single space. Each language name consists of up to twenty alphabetic
letters.
A line that contains two zeros indicates the end of input and is not part of a data set.
Output
Print a line that contains the minimum number
L
of languages to be spoken, followed by
L
language
names in any order. Each language name should be printed in a separate line. In case two or more sets of
the same size is possible, you may print any one of them. If it is impossible for the group to enjoy talking
with not more than five languages, you should print a single line that contains “Impossible” (without
quotes).
Print an empty line between data sets.
Sample Input
3 4
English
French
Japanese
1 English
2 French English
2 Japanese English
1 Japanese
2 2
English
Japanese
1 English
1 Japanese
6 7
English
Dutch
German
French
Italian
Spanish
1 English
2 English Dutch
2 Dutch German
2 German French
2 French Italian
2 Italian Spanish
1 Spanish
0 0
Output for the Sample Input
2
English
Japanese

Impossible

Impossible

Submitted solutions:

code_snippet: #include "bits/stdc++.h"
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/tag_and_trait.hpp>
using namespace __gnu_pbds;
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
#define rep(i, m, n) for (ll i = (ll)m; i < (ll)n; i++)
#define drep(i, m, n) for (ll i = m - 1; i >= n; i--)
#define Endl endl
#define all(a) a.begin(), a.end()
#define pr(i, j) make_pair(i, j)
#define isin(x, l, r) (l <= x && x < r)
#define chmin(a, b) a = min(a, b)
#define chmax(a, b) a = max(a, b)
#define srt(ar) sort(ar.begin(), ar.end())
#define rev(ar) reverse(ar.begin(), ar.end())
#define jge(f, s, t) cout << (f ? s : t) << endl
template <typename T>
using ordered_set = tree<T, null_type, std::less<T>, rb_tree_tag, tree_order_statistics_node_update>;
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#define printar(ar)             \
    do                          \
    {                           \
        for (auto dbg : ar)     \
        {                       \
            cout << dbg << " "; \
        }                       \
        cout << endl;           \
    } while (0)
const ll inf = 1e18;
const ld pi = 3.14159265358979;
const ld eps = 1e-9;
template <class T, ll n, ll idx = 0>
auto make_vec(const ll (&d)[n], const T &init) noexcept
{
    if constexpr (idx < n)
        return std::vector(d[idx], make_vec<T, n, idx + 1>(d, init));
    else
        return init;
}

template <class T, ll n>
auto make_vec(const ll (&d)[n]) noexcept
{
    return make_vec(d, T{});
}
//////////////// 以下を貼る ////////////////
template <class T>
size_t HashCombine(const size_t seed, const T &v)
{
    return seed ^ (std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
}
/* pair用 */
template <class T, class S>
struct std::hash<std::pair<T, S>>
{
    size_t operator()(const std::pair<T, S> &keyval) const noexcept
    {
        return HashCombine(std::hash<T>()(keyval.first), keyval.second);
    }
};
/* vector用 */
template <class T>
struct std::hash<std::vector<T>>
{
    size_t operator()(const std::vector<T> &keyval) const noexcept
    {
        size_t s = 0;
        for (auto &&v : keyval)
            s = HashCombine(s, v);
        return s;
    }
};
/* tuple用 */
template <int N>
struct HashTupleCore
{
    template <class Tuple>
    size_t operator()(const Tuple &keyval) const noexcept
    {
        size_t s = HashTupleCore<N - 1>()(keyval);
        return HashCombine(s, std::get<N - 1>(keyval));
    }
};
template <>
struct HashTupleCore<0>
{
    template <class Tuple>
    size_t operator()(const Tuple &keyval) const noexcept { return 0; }
};
template <class... Args>
struct std::hash<std::tuple<Args...>>
{
    size_t operator()(const tuple<Args...> &keyval) const noexcept
    {
        return HashTupleCore<tuple_size<tuple<Args...>>::value>()(keyval);
    }
};
template <typename Type3>
class union_find
{
private:
    vector<Type3> graph;
    vector<Type3> sum;

public:
    // n頂点のグラフを作成(添字は0から)
    union_find(Type3 n)
    {
        graph.resize(n);
        sum.resize(n);
        for (int i = 0; i < n; i++)
        {
            graph[i] = i;
            sum[i] = 1;
        }
    }
    // 頂点nの根を返す
    Type3 root(Type3 n)
    {
        if (graph[n] == n)
            return n;
        else
        {
            graph[n] = root(graph[n]);
            return graph[n];
        }
    }
    // union_findの内部構造,デバッグ
    void debug()
    {
        for (unsigned i = 0; i < graph.size(); i++)
        {
            cout << graph[i] << " ";
        }
        cout << endl;
        for (unsigned i = 0; i < graph.size(); i++)
        {
            cout << sum[i] << " ";
        }
        cout << endl;
    }
    // 頂点mから頂点nに向かって辺を引く
    void line(Type3 m, Type3 n)
    {
        if (check(m, n))
            return;
        sum[root(m)] += sum[root(n)];
        sum[root(n)] = 0;
        graph[root(n)] = root(m);
        graph[n] = root(m);
    }
    // 頂点nが属する連結成分の大きさを返す
    Type3 size(Type3 n)
    {
        return sum[root(n)];
    }
    // 頂点mと頂点nが連結なら1,非連結なら0を返す
    bool check(Type3 m, Type3 n)
    {
        return root(m) == root(n);
    }
};
/////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    bool isfirst = true;
    while (true)
    {
        ll n, m;
        cin >> n >> m;
        if (n == 0)
        {
            break;
        }
        else
        {
            if (isfirst)
            {
                isfirst = false;
            }
            else
            {
                cout << endl;
            }
        }
        vector<string> a(n);
        map<string, ll> mp;
        rep(i, 0, n)
        {
            string s;
            cin >> s;
            a[i] = s;
            mp[s] = i;
        }
        vector<vector<ll>> b(n);
        rep(i, 0, m)
        {
            ll t;
            cin >> t;
            rep(j, 0, t)
            {
                string s;
                cin >> s;
                b[mp[s]].push_back(i);
            }
        }
        bool f = false;
        rep(i, 1, min(n, 5LL) + 1)
        {
            vector<ll> ar(n, 0);
            rep(j, 0, i)
            {
                ar[j] = 1;
            }
            srt(ar);
            do
            {
                union_find<ll> uf(m);
                rep(j, 0, n)
                {
                    if (ar[j] == 1)
                    {
                        rep(k, 0, b[j].size())
                        {
                            uf.line(b[j][0], b[j][k]);
                        }
                    }
                }
                if (uf.size(0) == m)
                {
                    f = true;
                    cout << i << endl;
                    rep(j, 0, n)
                    {
                        if (ar[j] == 1)
                        {
                            cout << a[j] << endl;
                        }
                    }
                    goto nxt;
                }
            } while (next_permutation(all(ar)));
        }
    nxt:
        if (!f)
        {
            cout << "Impossible" << endl;
        }
    }
}
accuracy: 1
time_ms: 200
memory_kb: 3456
final_rank: 9

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
const ld eps = 1e-9;

template < class BidirectionalIterator >
bool next_combination(BidirectionalIterator first1,
	BidirectionalIterator last1,
	BidirectionalIterator first2,
	BidirectionalIterator last2)
{
	if ((first1 == last1) || (first2 == last2)) {
		return false;
	}
	BidirectionalIterator m1 = last1;
	BidirectionalIterator m2 = last2; --m2;
	while (--m1 != first1 && !(*m1 < *m2)) {
	}
	bool result = (m1 == first1) && !(*first1 < *m2);
	if (!result) {
		// ①
		while (first2 != m2 && !(*m1 < *first2)) {
			++first2;
		}
		first1 = m1;
		std::iter_swap(first1, first2);
		++first1;
		++first2;
	}
	if ((first1 != last1) && (first2 != last2)) {
		// ②
		m1 = last1; m2 = first2;
		while ((m1 != first1) && (m2 != last2)) {
			std::iter_swap(--m1, m2);
			++m2;
		}
		// ③
		std::reverse(first1, m1);
		std::reverse(first1, last1);
		std::reverse(m2, last2);
		std::reverse(first2, last2);
	}
	return !result;
}

template < class BidirectionalIterator >
bool next_combination(BidirectionalIterator first,
	BidirectionalIterator middle,
	BidirectionalIterator last)
{
	return next_combination(first, middle, middle, last);
}


struct UnionFind {
	vector<int> data;
	UnionFind(int size) : data(size, -1) { }
	bool unionSet(int x, int y) {
		x = root(x); y = root(y);
		if (x != y) {
			if (data[y] < data[x]) swap(x, y);
			data[x] += data[y]; data[y] = x;
		}
		return x != y;
	}
	int root(int x) {
		return data[x] < 0 ? x : data[x] = root(data[x]);
	}
	int size(int x) {
		return -data[root(x)];
	}
};


int main() {
	cout<<setprecision(10)<<fixed;

	int tt=false;
	while (true){
		int N,M;cin>>N>>M;
		if(!N)break;

		if (tt)cout << endl;
		tt = true;
		map<string,int>mp;
		map<int,string>revmp;
		{
			for (int i = 0; i < N; ++i) {
				string st;cin>>st;
				mp[st]=i;
				revmp[i]=st;
			}
		}
		vector<vector<int>>langs(M,vector<int>(N));
		for (int i = 0; i < M; ++i) {
			int k;cin>>k;
			for (int j = 0; j < k; ++j) {
				string st;cin>>st;
				langs[i][mp[st]]=true;
			}
		}
		vector<int>perms(N);
		iota(perms.begin(),perms.end(),0);

		vector<string>anss;

		for (int t = 1; t <= (min(N, 5)); ++t) {
			do {
				UnionFind uf(M + min(N, 5));
				for (int i = 0; i < M; ++i) {
					for (int j = 0; j < t; ++j) {
						int lang_id = perms[j];
						if (langs[i][lang_id])uf.unionSet(i, M + j);

						for (int k = 1; k <t; ++k) {
							int lang_id2 = perms[k];
							if (langs[i][lang_id] && langs[i][lang_id2]) {
								uf.unionSet(M + j, M + k);
							}
						}
					}
				}
				set<int>aset;
				for (int i = 0; i < M + t; ++i) {
					aset.emplace(uf.root(i));
				}
				if (aset.size() == 1) {
					for (int i = 0; i < t; ++i) {
						anss.emplace_back(revmp[perms[i]]);
					}
					break;
				}
			} while (next_combination(perms.begin(), perms.begin() + t, perms.end()));
			if(!anss.empty())break;
		}
		if (anss.empty()) {
			cout << "Impossible" << endl;
		}
		else {
			cout<<anss.size()<<endl;
			for(auto ans:anss)cout<<ans<<endl;
		}
	}
	return 0;
}
accuracy: 1
time_ms: 1720
memory_kb: 3068
final_rank: 13

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

int N,M;
char name[30][21];

int check[20];

int boss[20],height[20];
int POW[31];

int get_boss(int id){
	if(boss[id] == id)return id;
	else{
		return boss[id] = get_boss(boss[id]);
	}
}

void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	if(boss_x == boss_y)return;

	if(height[x] > height[y]){

		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void init(){
	for(int i = 0; i < M; i++){
		boss[i] = i;
		height[i] = 0;
	}
}

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

int data_set = 0;

void func(){

	if(data_set != 0){
		printf("\n");
	}
	data_set++;

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

	for(int i = 0; i < M; i++)check[i] = 0;

	char buf[21];
	int num;

	for(int i = 0; i < M; i++){
		scanf("%d",&num);
		for(int k = 0; k < num; k++){
			scanf("%s",buf);
			for(int p = 0; p < N; p++){
				if(strCmp(name[p],buf)){
					check[i] += POW[p];
					break;
				}
			}
		}
	}

	bool FLG;
	int S;

	for(int a = 0; a < N; a++){
		FLG = true;
		S = POW[a];

		for(int i = 0; i < M; i++){
			if((check[i] & S) == 0){
				FLG = false;
				break;
			}
		}

		if(FLG){
			printf("1\n");
			printf("%s\n",name[a]);
			return;
		}
	}

	if(N == 1){
		printf("Impossible\n");
		return;
	}

	int count;

	for(int a = 0; a < N-1; a++){
		for(int b = a+1; b < N; b++){
			S = POW[a]+POW[b];
			init();

			for(int i = 0; i < M-1; i++){
				for(int k = i+1; k < M; k++){
					if(check[i]&check[k]&S){
						unite(i,k);
					}
				}
			}

			count = 0;
			for(int i = 0; i < M; i++){
				if(get_boss(i) == i)count++;
			}

			if(count == 1){
				printf("2\n");
				printf("%s\n",name[a]);
				printf("%s\n",name[b]);
				return;
			}
		}
	}

	if(N == 2){
		printf("Impossible\n");
		return;
	}


	for(int a = 0; a < N-2; a++){
		for(int b = a+1; b < N-1; b++){
			for(int c = b+1; c < N; c++){
				S = POW[a]+POW[b]+POW[c];
				init();

				for(int i = 0; i < M-1; i++){
					for(int k = i+1; k < M; k++){
						if(check[i]&check[k]&S){
							unite(i,k);
						}
					}
				}

				count = 0;
				for(int i = 0; i < M; i++){
					if(get_boss(i) == i)count++;
				}

				if(count == 1){

					printf("3\n");
					printf("%s\n",name[a]);
					printf("%s\n",name[b]);
					printf("%s\n",name[c]);
					return;

				}
			}
		}
	}

	if(N == 3){
		printf("Impossible\n");
		return;
	}

	for(int a = 0; a < N-3; a++){
		for(int b = a+1; b < N-2; b++){
			for(int c = b+1; c < N-1; c++){
				for(int d = c+1; d < N; d++){
					S = POW[a]+POW[b]+POW[c]+POW[d];
					init();

					for(int i = 0; i < M-1; i++){
						for(int k = i+1; k < M; k++){
							if(check[i]&check[k]&S){
								unite(i,k);
							}
						}
					}

					count = 0;
					for(int i = 0; i < M; i++){
						if(get_boss(i) == i)count++;
					}

					if(count == 1){
						printf("4\n");
						printf("%s\n",name[a]);
						printf("%s\n",name[b]);
						printf("%s\n",name[c]);
						printf("%s\n",name[d]);
						return;
					}
				}
			}
		}
	}

	if(N == 4){
		printf("Impossible\n");
		return;
	}

	for(int a = 0; a < N-4; a++){
		for(int b = a+1; b < N-3; b++){
			for(int c = b+1; c < N-2; c++){
				for(int d = c+1; d < N-1; d++){
					for(int e = d+1; e < N; e++){
						S = POW[a]+POW[b]+POW[c]+POW[d]+POW[e];
						init();

						for(int i = 0; i < M-1; i++){
							for(int k = i+1; k < M; k++){
								if(check[i]&check[k]&S){
									unite(i,k);
								}
							}
						}

						count = 0;
						for(int i = 0; i < M; i++){
							if(get_boss(i) == i)count++;
						}

						if(count == 1){
							printf("5\n");
							printf("%s\n",name[a]);
							printf("%s\n",name[b]);
							printf("%s\n",name[c]);
							printf("%s\n",name[d]);
							printf("%s\n",name[e]);
							return;
						}
					}
				}
			}
		}
	}

	printf("Impossible\n");
}

int main(){

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

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

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 550
memory_kb: 3328
final_rank: 11

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

int N,M;
char name[30][21];

int check[20];

int boss[20],height[20];
int POW[31];

int get_boss(int id){
	if(boss[id] == id)return id;
	else{
		return boss[id] = get_boss(boss[id]);
	}
}

void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	if(boss_x == boss_y)return;

	if(height[x] > height[y]){

		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void init(){
	for(int i = 0; i < M; i++){
		boss[i] = i;
		height[i] = 0;
	}
}

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

int data_set = 0;

void func(){

	if(data_set != 0){
		printf("\n");
	}
	data_set++;

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

	for(int i = 0; i < M; i++)check[i] = 0;

	char buf[21];
	int num;

	for(int i = 0; i < M; i++){
		scanf("%d",&num);
		for(int k = 0; k < num; k++){
			scanf("%s",buf);
			for(int p = 0; p < N; p++){
				if(strCmp(name[p],buf)){
					check[i] += POW[p];
					break;
				}
			}
		}
	}

	bool FLG;
	int S;

	for(int a = 0; a < N; a++){
		FLG = true;
		S = POW[a];

		for(int i = 0; i < M; i++){
			if((check[i] & S) == 0){
				FLG = false;
				break;
			}
		}

		if(FLG){
			printf("1\n");
			printf("%s\n",name[a]);
			return;
		}
	}

	int count;

	for(int a = 0; a < N-1; a++){
		for(int b = a+1; b < N; b++){
			S = POW[a]+POW[b];
			init();

			for(int i = 0; i < M-1; i++){
				for(int k = i+1; k < M; k++){
					if(check[i]&check[k]&S){
						unite(i,k);
					}
				}
			}

			count = 0;
			for(int i = 0; i < M; i++){
				if(get_boss(i) == i)count++;
			}

			if(count == 1){
				printf("2\n");
				printf("%s\n",name[a]);
				printf("%s\n",name[b]);
				return;
			}
		}
	}


	for(int a = 0; a < N-2; a++){
		for(int b = a+1; b < N-1; b++){
			for(int c = b+1; c < N; c++){
				S = POW[a]+POW[b]+POW[c];
				init();

				for(int i = 0; i < M-1; i++){
					for(int k = i+1; k < M; k++){
						if(check[i]&check[k]&S){
							unite(i,k);
						}
					}
				}

				count = 0;
				for(int i = 0; i < M; i++){
					if(get_boss(i) == i)count++;
				}

				if(count == 1){

					printf("3\n");
					printf("%s\n",name[a]);
					printf("%s\n",name[b]);
					printf("%s\n",name[c]);
					return;

				}
			}
		}
	}

	for(int a = 0; a < N-3; a++){
		for(int b = a+1; b < N-2; b++){
			for(int c = b+1; c < N-1; c++){
				for(int d = c+1; d < N; d++){
					S = POW[a]+POW[b]+POW[c]+POW[d];
					init();

					for(int i = 0; i < M-1; i++){
						for(int k = i+1; k < M; k++){
							if(check[i]&check[k]&S){
								unite(i,k);
							}
						}
					}

					count = 0;
					for(int i = 0; i < M; i++){
						if(get_boss(i) == i)count++;
					}

					if(count == 1){
						printf("4\n");
						printf("%s\n",name[a]);
						printf("%s\n",name[b]);
						printf("%s\n",name[c]);
						printf("%s\n",name[d]);
						return;
					}
				}
			}
		}
	}

	for(int a = 0; a < N-4; a++){
		for(int b = a+1; b < N-3; b++){
			for(int c = b+1; c < N-2; c++){
				for(int d = c+1; d < N-1; d++){
					for(int e = d+1; e < N; e++){
						S = POW[a]+POW[b]+POW[c]+POW[d]+POW[e];
						init();

						for(int i = 0; i < M-1; i++){
							for(int k = i+1; k < M; k++){
								if(check[i]&check[k]&S){
									unite(i,k);
								}
							}
						}

						count = 0;
						for(int i = 0; i < M; i++){
							if(get_boss(i) == i)count++;
						}

						if(count == 1){
							printf("5\n");
							printf("%s\n",name[a]);
							printf("%s\n",name[b]);
							printf("%s\n",name[c]);
							printf("%s\n",name[d]);
							printf("%s\n",name[e]);
							return;
						}
					}
				}
			}
		}
	}

	printf("Impossible\n");
}

int main(){

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

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

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 580
memory_kb: 3328
final_rank: 12

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

using namespace std;

#define int long long
#define all(v) begin(v), end(v)
#define rep(i, n) for(int i = 0; i < (int)(n); i++)
#define reps(i, s, n) for(int i = (int)(s); i < (int)(n); i++)

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

using pint = pair<int, int>;
using tint = tuple<int, int, int>;
using vint = vector<int>;

const int inf = 1LL << 55;
const int mod = 1e9 + 7;

struct UnionFind
{
  vector<int> data;
  UnionFind(){}
  UnionFind(int sz):data(sz, -1){};
  int size(int x) { return -data[find(x)]; }
  int find(int x) { return data[x] < 0 ? x : data[x] = find(data[x]); }
  bool same(int x, int y) { return find(x) == find(y); }
  int unite(int x, int y)
  {
    x = find(x), y = find(y);
    if(x != y) {
      if(data[x] < data[y]) swap(x, y);
      data[x] += data[y]; data[y] = x;
    }
    return -data[x];
  }
  void init(int sz) {
    data.clear();
    data.resize(sz, -1);
  }
};

UnionFind uf;

int N, M;
vector<string> lang;
map<string, int> mp;
map<string, int> group;
vector<int> vec;
vector<string> ans;

bool input() {
  cin >> N >> M;
  if(!N && !M) return false;

  lang.clear();
  mp.clear();
  rep(i, N) {
    string l;
    cin >> l;
    lang.push_back(l);
    mp[l] = i;
  }

  vec.clear();
  group.clear();
  rep(i, M) {
    int k; cin >> k;
    int bit = 0;
    rep(j, k) {
      string l; cin >> l;
      bit |= 1<<mp[l];
      group[l] |= 1<<i;
    }
    vec.push_back(bit);
  }

  return true;
}

void solve(int idx, int bit) {
  if(__builtin_popcount(bit) > 5) return;
  if(uf.size(N) == __builtin_popcount(bit)+M) {
    if(ans.empty() || __builtin_popcountll(bit) < ans.size()) {
      ans.clear();
      rep(i, N) if((bit>>i)&1) ans.push_back(lang[i]);
    }
  }

  reps(i, idx, N) {
    if((bit>>i)&1) continue;
    UnionFind tmp = uf;
    rep(j, M) if((vec[j]>>i)&1) uf.unite(i, N+j);
    solve(i+1, bit|(1<<i));
    uf = tmp;
  }
}

signed main()
{
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(12);

  bool flag = false;
  while(input()) {
    if(flag) cout << endl;
    flag = true;

    ans.clear();
    uf.init(N+M);
    solve(0, 0);
    if(ans.size()) {
      cout << ans.size() << endl;
      for(string l : ans) cout << l << endl;
    } else {
      cout << "Impossible" << endl;
    }
  }
  return 0;
}
accuracy: 1
time_ms: 2090
memory_kb: 3044
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;
int p[51],r[51];
void init(){for(int i=0;i<50;i++)p[i]=i,r[i]=0;}
int find(int x){return (p[x]==x)?x:(p[x]=find(p[x]));}
void unite(int x,int y) {
  x=find(x),y=find(y);
  if(x==y)return;
  if(r[x]<r[y])p[x]=y;
  else{p[y]=x;if(r[x]==r[y])r[x]++;}
}
bool same(int x,int y){return find(x)==find(y);}
vector<string> s,ans;
set<string> se[50];
int n,m;
 
void dfs(int k,int t) {
  bool f=1;
  for(int i=1; i<m; i++) if(!same(0,i)) {f=0;break;}
  if(f) {
    if(!ans.size()||ans.size()>__builtin_popcount(t)) {
      ans.clear();
      for(int i=0; i<n; i++) if(t&(1<<i)) ans.push_back(s[i]);
    }
    return;
  }
  if(k>=n) return;
  for(int i=k; i<n; i++) {
    if(__builtin_popcount(t|(1<<i))>5) continue;
    int l=0;
    while(l<m&&!se[l].count(s[i])) l++;
    if(l==m) continue;
    int pp[m],rr[m];
    for(int j=0; j<m; j++) pp[j]=p[j],rr[j]=r[j];
    for(int j=l+1; j<m; j++) {
      if(se[j].count(s[i])) unite(l,j);
    }
    dfs(i+1,t|(1<<i));
    for(int j=0; j<m; j++) p[j]=pp[j],r[j]=rr[j];
  }
}
 
int main() {
  int f=0;
  while(cin>>n>>m&&n) {
    if(f) cout<<endl;
    f=1;
    init();
    ans.clear();
    s.clear();
    for(int i=0; i<n; i++) {
      string t;cin>>t;
      s.push_back(t);
    }
    for(int i=0; i<m; i++) {
      se[i].clear();
      int k;cin>>k;
      for(int j=0; j<k; j++) {
        string t;cin>>t;
        se[i].insert(t);
      }
    }
    dfs(0,0);
    if(ans.size()) {
      cout<<ans.size()<<endl;
      for(int i=0; i<ans.size(); i++)cout<<ans[i]<<endl;
    } else cout<<"Impossible"<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 1930
memory_kb: 3088
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
int A[21];
int lan[30];
int m,n;

vector<int>ans,used;

void dfs(int dep,int member,int use){
  if(member == (1<<n)-1) {
    if(ans.size()==0 || ans.size()> used.size()) ans = used;
    return ;
  }
  
  if(dep >= m || dep>=5)return;
  
  for(int i=0;i<m;i++){
    if(use&&(use>>i&1)==0) continue;
    
    int nmember = member | lan[i];
    int nuse = use;
    for(int j=0;j<n;j++)
      if(lan[i]>>j&1) nuse |= A[j];
    
    used.push_back(i);
    dfs(dep+1,nmember,nuse);
    used.pop_back();
  }
}

int main(){
  int flg = 0;
  while(1){
    
  cin>>m>>n;
  if(!m&&!n)break;
  if(flg++) cout<<endl;
  map<string,int> M;
  string name[30];
  for(int i=0;i<m;i++){
    string str;
    cin>>str;
    M[str] = i;
    name[i] = str;
  }

  memset(lan,0,sizeof(lan));
  memset(A,0,sizeof(A));
  
  for(int i=0;i<n;i++){
    int k;
    cin>>k;
    for(int j=0;j<k;j++){
      string str;
      cin>>str;
      A[i] |= 1<<M[str];
      lan[M[str]] |= 1<<i;
    }
  }

  ans.clear();used.clear();
  dfs(0,0,0);
  if(ans.size()==0) cout<<"Impossible"<<endl;
  else {
    cout<<ans.size()<<endl;
    for(int i=0;i<ans.size();i++)cout<<name[ans[i]]<<endl;
  }
  }
  return 0;
}
accuracy: 1
time_ms: 6180
memory_kb: 3188
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
int p[51],r[51];
void init(){for(int i=0;i<50;i++)p[i]=i,r[i]=0;}
int find(int x){return (p[x]==x)?x:(p[x]=find(p[x]));}
void unite(int x,int y) {
  x=find(x),y=find(y);
  if(x==y)return;
  if(r[x]<r[y])p[x]=y;
  else{p[y]=x;if(r[x]==r[y])r[x]++;}
}
bool same(int x,int y){return find(x)==find(y);}
vector<string> s,ans;
set<string> se[50];
int n,m;

void dfs(int k,int t) {
  bool f=1;
  for(int i=1; i<m; i++) if(!same(0,i)) f=0;
  if(f) {
    if(!ans.size()||ans.size()>__builtin_popcount(t)) {
      ans.clear();
      for(int i=0; i<n; i++) {
        if(t&(1<<i)) ans.push_back(s[i]);
      }
    }
    return;
  }
  if(k>=n) return;
  for(int i=k; i<n; i++) {
    if(__builtin_popcount(t|(1<<i))>5) continue;
    int l=0;
    while(l<m&&!se[l].count(s[i])) l++;
    if(l==m) continue;
    int pp[m],rr[m];
    for(int j=0; j<m; j++) pp[j]=p[j],rr[j]=r[j];
    for(int j=l+1; j<m; j++) {
      if(se[j].count(s[i])) unite(l,j);
    }
    dfs(i+1,t|(1<<i));
    for(int j=0; j<m; j++) p[j]=pp[j],r[j]=rr[j];
  }
}

int main() {
  int f=0;
  while(cin >> n >> m && n) {
    if(f) cout << endl;
    f=1;
    init();
    ans.clear();
    s.clear();
    for(int i=0; i<n; i++) {
      string t;
      cin >> t;
      s.push_back(t);
    }
    for(int i=0; i<m; i++) {
      se[i].clear();
      int k;
      cin >> k;
      for(int j=0; j<k; j++) {
        string t;
        cin >> t;
        se[i].insert(t);
      }
    }
    dfs(0,0);
    if(ans.size()) {
      cout << ans.size() << endl;
      for(int i=0; i<ans.size(); i++) cout << ans[i] << endl;
    } else cout << "Impossible" << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 2300
memory_kb: 3168
final_rank: 17

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

using namespace std;

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

namespace tree {
struct union_find {
  static const int Max = 22;
  int par[Max], rank[Max], size[Max], compnum;

  union_find(int N) {
    compnum = N;
    for(int i=0; i<N; i++) {
      par[i] = i;
      rank[i] = 0;
      size[i] = 1;
    }
  }

  int root(int x) {
    return par[x] == x ? x : par[x] = root(par[x]);
  }

  void unite(int x, int y) {
    x = root(x), y = root(y);
    if(x == y) return;
    if(rank[x] < rank[y]) {
      par[x] = y, size[y] += size[x];
    } else {
      par[y] = x, size[x] += size[y];
      if(rank[x] == rank[y]) rank[x]++;
    }
    compnum--;
  }

  int operator[](int x) { return root(x); }
  void operator()(int x, int y) { return unite(x, y); }

  bool same(int x, int y) { return root(x) == root(y); }
  int size_of(int x) { return size[root(x)]; }
  int num_of_comps() { return compnum; }
};
}

int N, M;
unordered_map<string, int> idmap;
vector<string> langs;
bool speaks[23][33];

void input() {
  langs.clear(); langs.resize(N);
  rep(i, N) {
    cin >> langs[i];
    idmap[langs[i]] = i;
  }
  memset(speaks, 0, sizeof speaks);
  rep(i, M) {
    int k; cin >> k;
    rep(_, k) {
      string s; cin >> s;
      speaks[i][idmap[s]] = 1;
    }
  }
}

bool next_combination(int& comb, int const BitSize) {
  int x = comb & -comb, y = comb + x;
  comb = ((comb & ~y) / x >> 1) | y;
  return comb < 1 << BitSize;
}

void solve() {

  REP(K, 1, min(N + 1, 6)) {
    int comb = (1 << K) - 1;
    do {
      vector<int> uselangs;
      rep(i, N) {
        if(!(comb & 1 << i)) continue;
        uselangs.push_back(i);
      }

      tree::union_find uf(M);

      rep(i, M) REP(j, i + 1, M)
        for(auto langid: uselangs)
          if(speaks[i][langid] && speaks[j][langid])
            uf(i, j);

      if(uf.num_of_comps() == 1) {
        printf("%d\n", (int)uselangs.size());
        for(auto e: uselangs) printf("%s\n", langs[e].c_str());
        return;
      }
    } while(next_combination(comb, N));
  }
  puts("Impossible");
}

int main() {
  bool first = 0;
  for(; cin >> N >> M && (N|M);) {
    if(first) cout << endl;
    first = 1;
    input();
    solve();
  }
  
  return 0;
}
accuracy: 1
time_ms: 2100
memory_kb: 3364
final_rank: 19

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

using namespace std;

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

namespace tree {
struct union_find {
  static const int Max = 22;
  int par[Max], rank[Max], size[Max], compnum;

  union_find(int N) {
    compnum = N;
    for(int i=0; i<N; i++) {
      par[i] = i;
      rank[i] = 0;
      size[i] = 1;
    }
  }

  int root(int x) {
    return par[x] == x ? x : par[x] = root(par[x]);
  }

  void unite(int x, int y) {
    x = root(x), y = root(y);
    if(x == y) return;
    if(rank[x] < rank[y]) {
      par[x] = y, size[y] += size[x];
    } else {
      par[y] = x, size[x] += size[y];
      if(rank[x] == rank[y]) rank[x]++;
    }
    compnum--;
  }

  int operator[](int x) { return root(x); }
  void operator()(int x, int y) { return unite(x, y); }

  bool same(int x, int y) { return root(x) == root(y); }
  int size_of(int x) { return size[root(x)]; }
  int num_of_comps() { return compnum; }
};
}

int N, M;
unordered_map<string, int> idmap;
vector<string> langs;
bool speaks[23][33];

void input() {
  langs.clear(); langs.resize(N);
  rep(i, N) {
    cin >> langs[i];
    idmap[langs[i]] = i;
  }
  memset(speaks, 0, sizeof speaks);
  rep(i, M) {
    int k; cin >> k;
    rep(_, k) {
      string s; cin >> s;
      speaks[i][idmap[s]] = 1;
    }
  }
}

bool next_combination(int& comb, int const BitSize) {
  // Assume: comb := (1 << K) - 1, K <= BitSize
  int x = comb & -comb, y = comb + x;
  comb = ((comb & ~y) / x >> 1) | y;
  return comb < 1 << BitSize;
}

void solve() {

  REP(K, 1, min(N + 1, 6)) {
    int comb = (1 << K) - 1;
    do {
      vector<int> uselangs;
      rep(i, N) {
        if(!(comb & 1 << i)) continue;
        uselangs.push_back(i);
      }

      tree::union_find uf(M);

      rep(i, M) REP(j, i + 1, M)
        for(auto langid: uselangs)
          if(speaks[i][langid] && speaks[j][langid])
            uf(i, j);

      if(uf.num_of_comps() == 1) {
        printf("%d\n", (int)uselangs.size());
        for(auto e: uselangs) printf("%s\n", langs[e].c_str());
        return;
      }
    } while(next_combination(comb, N));
  }
  puts("Impossible");
}

string to_binary(int x, int const LeastDigit = 0) {
  string ret;
  while(x) ret.push_back(x % 2 + '0'), x /= 2;
  for(int i=ret.size(); i<LeastDigit; i++) ret.push_back('0');
  reverse(ret.begin(), ret.end());
  return ret;
}

int main() {
  bool first = 0;
  for(; cin >> N >> M && (N|M);) {
    if(first) cout << endl;
    first = 1;
    input();
    solve();
  }
  
  return 0;
}
accuracy: 1
time_ms: 2050
memory_kb: 3376
final_rank: 18

code_snippet: #include <bits/stdc++.h>
 
using namespace std;
 
#define MAX_N 30
#define MAX_M 20
#define INF (1<<29)
 
int N,M,mini,ansS;
bool edge[MAX_M][MAX_N];
 
class Union_Find{
public:
    int par[MAX_M],rank[MAX_M],size[MAX_M];
    Union_Find(int N){
	for(int i = 0 ; i < N ; i++){
	    par[i] = i;
	    rank[i] = 0;
	    size[i] = 1;
	}
    }
 
    int find(int x){
	if(par[x] == x){
	    return x;
	}
	return par[x] = find(par[x]);
    }
 
    void unite(int x,int y){
	x = find(x);
	y = find(y);
	if(x == y) return;
	if(rank[x] < rank[y]){
	    par[x] = y;
	    size[y] += size[x];
	}else{
	    par[y] = x;
	    size[x] += size[y];
	    if(rank[x] == rank[y]){
		rank[x]++;
	    }
	}
    }
 
    bool same(int x,int y){
	return find(x) == find(y);
    }
 
    int getSize(int x){
	return size[find(x)];
    }
};
 
bool check(int S){
    int idx = 0,arr[MAX_M];
    if(S == 0) return false;
    for(int i = 0 ; i < N ; i++){
	if(S >> i & 1){
	    arr[idx++] = i;
	}
    }
    Union_Find uf(M);
    for(int i = 0 ; i < M ; i++){
	for(int j = i+1 ; j < M ; j++){
	    if(uf.same(i,j)) continue;
	    for(int k = 0 ; k < idx ; k++){
		if(edge[i][arr[k]] && edge[j][arr[k]]){
		    uf.unite(i,j);
		}
	    }
	}
    }
    return (uf.getSize(0) == M);
}
 
void rec(int idx,int S,int num){
    if(num < mini && check(S)){
	mini = num; ansS = S;
	return;
    }
    if(num == 5 || num >= mini) return;
    for(int i = idx ; i < N ; i++){
	if(S >> i & 1) continue;
	rec(i+1,S|(1<<i),num+1);
    }
}
 
int main(){
    int K;
    bool blank = false;
    string lang[MAX_N],in;
    while(cin >> N >> M, N){
	map<string,int> mp;
	memset(edge,false,sizeof(edge));
	if(blank){ cout << endl; }
	blank = true;
	for(int i = 0 ; i < N ; i++){
	    cin >> lang[i];
	    mp[lang[i]] = i;
	}
	for(int i = 0 ; i < M ; i++){
	    cin >> K;
	    for(int j = 0 ; j < K ; j++){
		cin >> in;
		edge[i][mp[in]] = true;
	    }
	}
	mini = INF;
	rec(0,0,0);
	if(mini == INF){
	    cout << "Impossible" << endl;
	}else{
	    cout << __builtin_popcount(ansS) << endl;
	    for(int i = 0 ; i < N ; i++){
		if(ansS >> i & 1){
		    cout << lang[i] << endl;
		}
	    }
	}
    }
    return 0;
}
accuracy: 1
time_ms: 2350
memory_kb: 3148
final_rank: 16

code_snippet: #define _USE_MATH_DEFINES
#define INF 0x3f3f3f3f
#include <iostream>
#include <cstdio>
#include <sstream>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <limits>
#include <map>
#include <string>
#include <cstring>
#include <set>
#include <deque>
#include <bitset>
#include <list>
#include <complex>
#include <assert.h>

using namespace std;

typedef long long ll;
typedef pair <int,int> P;

static const double EPS = 1e-12;

static const int tx[] = {+0,+1,+0,-1};
static const int ty[] = {-1,+0,+1,+0};

class UnionFindTree {
  int* _par;
  int* _rank;
public:
  UnionFindTree(int N){
    _par = new int[N];
    _rank = new int[N];
    for(int i = 0; i < N; i++){
      _par[i] = i;
      _rank[i] = 0;
    }
  }

  ~UnionFindTree(){
    delete[] _par;
    delete[] _rank;
  }

  int find(int u){
    if(_par[u] == u) return u;
    return find(_par[u]);
  }

  bool unite(int u,int v){
    u = find(u);
    v = find(v);
    if(u == v) return false;
    
    if(_rank[u] < _rank[v]){
      _par[u] = v;
    }
    else{
      _par[v] = u;
      if(_rank[u] == _rank[v]) _rank[u]++;
    }
    return true;
  }
};

int main(){
  int num_of_languages;
  int num_of_students;
  bool is_first = true;
  while(~scanf("%d %d",&num_of_languages,&num_of_students)){
    if(num_of_languages == 0 && num_of_students == 0){
      break;
    }
    if(!is_first){
      printf("\n");
    }
    map<string,int> lang2idx;
    map<int,string> idx2lang;
    for(int lang_i = 0; lang_i < num_of_languages; lang_i++){
      string lang;
      cin >> lang;
      lang2idx[lang] = lang_i;
      idx2lang[lang_i] = lang;
    }

    int students[21] = {};
    for(int student_i = 0; student_i < num_of_students; student_i++){
      int num_of_skills;
      scanf("%d",&num_of_skills);
      for(int skill_i = 0; skill_i < num_of_skills; skill_i++){
        string skill;
        cin >> skill;
        students[student_i] |= (1 << lang2idx[skill]);
      }
    }

    int res = 0;


    for(int used = 1; used <= 5; used++){
      vector<int> languages;
      for(int i = 0; i < min(used,num_of_languages); i++){
        languages.push_back(1);
      }
      for(int i = 0; i < num_of_languages - used; i++){
        languages.push_back(0);
      }
      
      sort(languages.begin(),languages.end());
      do {
        int S = 0;
        for(int i = 0; i < languages.size(); i++){
          if(languages[i] == 1){
            S |= (1<<i);
          }
        }
        UnionFindTree uft(30);
        for(int student_i = 0; student_i < num_of_students; student_i++){
          for(int student_j = student_i + 1; student_j < num_of_students; student_j++){
            if(students[student_i] & students[student_j] & S){
              uft.unite(student_i,student_j);
            }
          }
        }
        
        set<int> parents;
        for(int student_i = 0; student_i < num_of_students; student_i++){
          parents.insert(uft.find(student_i));
        }
        if(parents.size() == 1){
          res = S;
          goto found;
        }
      } while(next_permutation(languages.begin(),languages.end()));
    }
  found:;

    if(res != 0){
      cout << __builtin_popcount(res) << endl;
      for(int lang_i = 0; lang_i < num_of_languages; lang_i++){
        if(res & (1<<lang_i)){
          cout << idx2lang[lang_i] << endl;
        }
      }
    }
    else{
      cout << "Impossible" << endl;
    }
    is_first = false;
  }
}
accuracy: 1
time_ms: 1340
memory_kb: 1292
final_rank: 5

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

using namespace std;

#define MAX_N 30
#define MAX_M 20
#define INF (1<<29)

int N,M,mini,ansS;
bool edge[MAX_M][MAX_N];

class Union_Find{
public:
  int par[MAX_M],rank[MAX_M],size[MAX_M];
  Union_Find(int N){
    for(int i = 0 ; i < N ; i++){
      par[i] = i;
      rank[i] = 0;
      size[i] = 1;
    }
  }

  int find(int x){
    if(par[x] == x){
      return x;
    }
    return par[x] = find(par[x]);
  }

  void unite(int x,int y){
    x = find(x);
    y = find(y);
    if(x == y){ return; }
    if(rank[x] < rank[y]){
      par[x] = y;
      size[y] += size[x];
    }else{
      par[y] = x;
      size[x] += size[y];
      if(rank[x] == rank[y]){
        rank[x]++;
      }
    }
  }

  bool same(int x,int y){
    return find(x) == find(y);
  }

  int getSize(int x){
    return size[find(x)];
  }
};

bool check(int S){
  int idx = 0,arr[MAX_M];
  if(S == 0){ return false; }
  for(int i = 0 ; i < N ; i++){
    if(S >> i & 1){
      arr[idx++] = i;
    }
  }
  Union_Find uf(M);
  for(int i = 0 ; i < M ; i++){
    for(int j = i+1 ; j < M ; j++){
      if(uf.same(i,j)){ continue; }
      for(int k = 0 ; k < idx ; k++){
        if(edge[i][arr[k]] && edge[j][arr[k]]){
          uf.unite(i,j);
        }
      }
    }
  }
  return (uf.getSize(0) == M);
}

void rec(int idx,int S,int num){
  if(num < mini && check(S)){
    mini = num; ansS = S;
    return;
  }
  if(num == 5 || num >= mini){ return; }
  for(int i = idx ; i < N ; i++){
    if(S >> i & 1){ continue; }
    rec(i+1,S|(1<<i),num+1);
  }
}

int main(){
  int K;
  bool blank = false;
  string lang[MAX_N],in;
  while(cin >> N >> M, N){
    map<string,int> mp;
    memset(edge,false,sizeof(edge));
    if(blank){ cout << endl; }
    blank = true;
    for(int i = 0 ; i < N ; i++){
      cin >> lang[i];
      mp[lang[i]] = i;
    }
    for(int i = 0 ; i < M ; i++){
      cin >> K;
      for(int j = 0 ; j < K ; j++){
        cin >> in;
        edge[i][mp[in]] = true;
      }
    }
    mini = INF;
    rec(0,0,0);
    if(mini == INF){
      cout << "Impossible" << endl;
    }else{
      cout << __builtin_popcount(ansS) << endl;
      for(int i = 0 ; i < N ; i++){
        if(ansS >> i & 1){
          cout << lang[i] << endl;
        }
      }
    }
  }
  return 0;
}
accuracy: 1
time_ms: 3090
memory_kb: 1224
final_rank: 7

code_snippet: #include<stdio.h>
#include<algorithm>
#include<string>
#include<map>
using namespace std;
char in[1100];
int c[40][40];
string t[40];
int v[40];
int n;
int sz;
int ret;
int ans[40];
int UF[40];
int FIND(int a){
	if(UF[a]<0)return a;
	return UF[a]=FIND(UF[a]);
}
void UNION(int a,int b){
	a=FIND(a);b=FIND(b);if(a==b)return;UF[a]+=UF[b];UF[b]=a;
}
void solve(int a,int b){
	if(ret==a)return ;
	bool ok=true;
	for(int i=0;i<sz;i++)UF[i]=-1;
	for(int i=0;i<sz;i++){
		for(int j=i+1;j<sz;j++){
			bool OK=false;
			for(int k=0;k<a;k++)if(c[i][v[k]]&&c[j][v[k]])OK=true;
			if(OK)UNION(i,j);
		}
	}
	if(UF[FIND(0)]==-sz){
		ret=a;
		for(int i=0;i<a;i++)ans[i]=v[i];
		return;
	}
	for(int i=b;i<n;i++){
		v[a]=i;
		solve(a+1,i+1);
	}
}
int main(){
	int a,b;
	bool se=false;
	while(scanf("%d%d",&a,&b),a){
		if(se)printf("\n");
		se=true;
		map<string,int>m;
		n=a;
		sz=b;
		ret=6;
		for(int i=0;i<a;i++){
			scanf("%s",in);
			string tmp=in;
			t[i]=tmp;
			m[tmp]=i;
		}
		for(int i=0;i<40;i++)for(int j=0;j<40;j++)c[i][j]=0;
		for(int i=0;i<b;i++){
			int d;scanf("%d",&d);
			for(int j=0;j<d;j++){
				scanf("%s",in);
				string tmp=in;
				c[i][m[tmp]]=1;
			}
		}
		
		for(int i=0;i<a;i++)v[i]=0;
		solve(0,0);
		if(ret==6){
			printf("Impossible\n");
		}else{
			printf("%d\n",ret);
			for(int i=0;i<ret;i++)printf("%s\n",t[ans[i]].c_str());
		}
	}
}
accuracy: 1
time_ms: 2220
memory_kb: 1100
final_rank: 6

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

struct UnionFind {
  vector<int> data;
  UnionFind(int size) : data(size, -1) { }
  bool unionSet(int x, int y) {
    x = root(x); y = root(y);
    if (x != y) {
      if (data[y] < data[x]) swap(x, y);
      data[x] += data[y]; data[y] = x;
    }
    return x != y;
  }
  bool findSet(int x, int y) {
    return root(x) == root(y);
  }
  int root(int x) {
    return data[x] < 0 ? x : data[x] = root(data[x]);
  }
  int size(int x) {
    return -data[root(x)];
  }
};


int N,M;
vector<string> cand;
map<string, vector<int> > dic;
map<string,int> id;

int check(vector<string> lan){
	UnionFind uf(N+M);
	for( auto item : lan ){
		int u = id[item];
		
		for( auto v : dic[item] )
			uf.unionSet(u+M,v);
	}

	for(int i = 0 ; i < M ; i++)
		if( !uf.findSet(0,i) ) return false;
	return true;
}
int good = 6;
vector<string> answer;
vector<string> now;
int cur;
int dfs(int x){
	if( good <= cur ) return 0;
	if( check(now) ){
		answer = now;
		good = cur;
		return 0;
	}
	if( N <= x ) return 0;
	dfs(x+1);
	
	cur++;
	now.push_back(cand[x]);
	dfs(x+1);
	now.pop_back();
	cur--;
	
}
int main(){
	int fst = 0;
	while(cin >> N >> M && N){
		if(fst++)cout << endl;
		cand.clear();
		dic.clear();
		for(int i = 0 ; i < N ; i++){
			string t;
			cin >> t;
			cand.push_back(t);
		}
		for(int k = 0 ; k < M ; k++){
			int t;
			cin >> t;
			for(int j = 0 ; j < t ; j++){
				string s;
				cin >> s;
				dic[s].push_back(k);
			}
		}
		int k = 0;
		for( auto x : dic){
			id[x.first] = k++;
		}
		good = 6;
		cur = 0;
		dfs(0);
		if( good >= 6 ){
			cout << "Impossible" << endl;
		}else{
			cout << good << endl;
			for(int i = 0 ; i < answer.size() ; i++){
				cout << answer[i] << endl;
			}
		}
	}
}
accuracy: 1
time_ms: 5670
memory_kb: 1364
final_rank: 10

code_snippet: #include<iostream>
#include<cstdio>
#include<cmath>
#include<cassert>
#include<climits>
#include<set>
#include<vector>
#include<algorithm>
#include<map>
#include<bitset>
#include<deque>
 
#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define IINF (INT_MAX)
#define MAX 35
 
using namespace std;
 
int N,M,dex,limit;
deque<int> ans;
vector<string> LG;
map<string,int> Index;
vector<int> G[MAX];
vector<int> bitG;
set<int> input[MAX];
string country;
bool used[MAX];
 
void cdfs(int cur,deque<int>& selected){
  if(used[cur])return;
  used[cur] = true;
  //cout << "cur = " << cur << endl;
  for(int i=0;i<G[cur].size();i++){
    int next = G[cur][i];
 
    if(used[next])continue;
 
    bool ok = false;
    for(int j=0;j<selected.size();j++){
      int one = selected[j];
      if( ( (bitG[one]>>cur) & 1 ) && ( (bitG[one]>>next) & 1 ) ){
    ok = true;
    break;
      }
    }

    if(ok){
      //cout << "from " << cur << " to " << next << endl;
      cdfs(next,selected);
    }
  }
}
 
 
bool check(deque<int>& selected){
  for(int i=0;i<M;i++)used[i] = false;
 
  int OK = bitG[selected[0]];
  while(OK){
    int use = OK & -OK;
    int cur = log2(use);
    OK -= use;
    cdfs(cur,selected);
  }
 
  for(int i=0;i<M;i++)if(!used[i])return false;
  return true;
}
 
void dfs(int cur,int language,int student,deque<int>& selected){
 
  if(language >= limit || language >= 6){
    return;
  }
 
  if(student == (1<<M)-1){
    if(!check(selected))return;
    if(limit > language){
      limit = language;
      ans = selected;
    }
    return;
  }
 
  for(int i=cur;i<N;i++){
    selected.push_back(i);
    dfs(i+1,language+1,student|bitG[i],selected);
    selected.pop_back();
  }
 
}
 
 
int main(){
 
  bool first = true;
  while(cin >> N >> M,N|M){
 
    if(!first)puts("");
    first = false;
 
    //init
    LG.clear();
    dex = 0;
    Index.clear();
    bitG.clear();
    ans.clear();
    for(int i=0;i<max(N,M);i++){
      G[i].clear();
      input[i].clear();
    }
      
    bitG.resize(N,0);
 
    for(int i=0;i<N;i++){
      cin >> country;
      LG.push_back(country);
      Index[country] = dex++;
    }
 
    int k;
    for(int i=0;i<M;i++){
      cin >> k;
      for(int j=0;j<k;j++){
    cin >> country;
    int index = Index[country];
    input[i].insert(index);
    bitG[index] |= (1<<i);
      }
    }
 
    //make graph
    for(int i=0;i<M;i++){
      for(int j=i+1;j<M;j++){
    for(set<int>::iterator it = input[i].begin(); it != input[i].end(); it++){
      int value = *it;
      if(input[j].find(value) != input[j].end()){
        G[i].push_back(j);
        G[j].push_back(i);
      }
    }
      }
    }
   
    limit = IINF;
    deque<int> deq;
    dfs(0,0,0,deq);
 
    if(limit == IINF){
      cout << "Impossible" << endl;
    } else {
      cout << limit << endl;
      for(int i=0;i<limit;i++){
    cout << LG[ans[i]] << endl;
      }
    }
 
 
  }
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 1320
final_rank: 1

code_snippet: #include<iostream>
#include<cstdio>
#include<cmath>
#include<cassert>
#include<climits>
#include<set>
#include<vector>
#include<algorithm>
#include<map>
#include<bitset>
#include<deque>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define IINF (INT_MAX)
#define MAX 35

using namespace std;

int N,M,dex,limit;
deque<int> ans;
vector<string> LG;
map<string,int> Index;
vector<int> G[MAX];
vector<int> bitG;
set<int> input[MAX];
string country;
bool used[MAX];

void cdfs(int cur,deque<int>& selected){
  if(used[cur])return;
  used[cur] = true;
  //cout << "cur = " << cur << endl;
  for(int i=0;i<G[cur].size();i++){
    int next = G[cur][i];

    if(used[next])continue;

    bool ok = false;
    for(int j=0;j<selected.size();j++){
      int one = selected[j];
      if( ( (bitG[one]>>cur) & 1 ) && ( (bitG[one]>>next) & 1 ) ){
	ok = true;
	break;
      }
    }
    /*
    for(int j=0;j<selected.size();j++){
      int one = selected[j];
      for(int k=j;k<selected.size();k++){
	int two = selected[k];
	if( ( ((bitG[one]>>cur)&1) & ((bitG[two]>>next)&1) ) || ( ((bitG[two]>>cur)&1) & ((bitG[one]>>next)&1) )  ){
	  cout << "from " << cur << " to " << next << " is ok because they have " << LG[one] << " and " << LG[two] << endl;
	  ok = true;
	  goto Skip;
	}
      }
    }
  Skip:;
    */
    if(ok){
      //cout << "from " << cur << " to " << next << endl;
      cdfs(next,selected);
    }
  }
}


bool check(deque<int>& selected){
  for(int i=0;i<M;i++)used[i] = false;

  int OK = bitG[selected[0]];
  while(OK){
    int use = OK & -OK;
    int cur = log2(use);
    OK -= use;
    cdfs(cur,selected);
  }

  for(int i=0;i<M;i++)if(!used[i])return false;
  return true;
}

void dfs(int cur,int language,int student,deque<int>& selected){

  if(language >= limit || language >= 6){
    return;
  }

  if(student == (1<<M)-1){
    if(!check(selected))return;
    if(limit > language){
      limit = language;
      ans = selected;
    }
    return;
  }

  for(int i=cur;i<N;i++){
    selected.push_back(i);
    dfs(i+1,language+1,student|bitG[i],selected);
    selected.pop_back();
  }

}


int main(){

  bool first = true;
  while(cin >> N >> M,N|M){

    if(!first)puts("");
    first = false;

    //init
    LG.clear();
    dex = 0;
    Index.clear();
    bitG.clear();
    ans.clear();
    for(int i=0;i<max(N,M);i++){
      G[i].clear();
      input[i].clear();
    }
     
    bitG.resize(N,0);

    for(int i=0;i<N;i++){
      cin >> country;
      LG.push_back(country);
      Index[country] = dex++;
    }

    int k;
    for(int i=0;i<M;i++){
      cin >> k;
      for(int j=0;j<k;j++){
	cin >> country;
	int index = Index[country];
	input[i].insert(index);
	bitG[index] |= (1<<i);
      }
    }

    //make graph
    for(int i=0;i<M;i++){
      for(int j=i+1;j<M;j++){
	for(set<int>::iterator it = input[i].begin(); it != input[i].end(); it++){
	  int value = *it;
	  if(input[j].find(value) != input[j].end()){
	    G[i].push_back(j);
	    G[j].push_back(i);
	  }
	}
      }
    }
    /*    
    rep(i,N){
      bitset<10> state = bitG[Index[LG[i]]];
      cout << LG[i] << " = " << Index[LG[i]] << " " << state << endl;
    }

    deque<int> deq;
    deq.push_back(0);
    deq.push_back(1);
    deq.push_back(3);
    deq.push_back(5);
    cout << check(deq) << endl;
    */
    limit = IINF;
    deque<int> deq;
    dfs(0,0,0,deq);

    if(limit == IINF){
      cout << "Impossible" << endl;
    } else {
      cout << limit << endl;
      for(int i=0;i<limit;i++){
	cout << LG[ans[i]] << endl;
      }
    }


  }
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 1320
final_rank: 1

code_snippet: #include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <algorithm>
#include <stack>
#include <queue>
#include <deque>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cassert>
#define REP(i,n) for(int i=0; i<(int)(n); ++i)

using namespace std;
typedef long long ll;

const int    INF = 1000000000;
const int    MOD = 1000000007;
const double EPS = 1e-8;

int nextcomb(int S){
    int x = S & -S;
    int y = S + x;
    S = ((S & ~y) / x >> 1) | y;
    return S;
}

int main(){
    for(int N, M, first = 1; cin >> N >> M && N; first = 0){
        if(!first) cout << endl;

        vector<string> lang(N);
        map<string, int> lang_dic;
        REP(i, N){
            string s; cin >> s;
            lang[i] = s;
            lang_dic[s] = i;
        }

        bool have[30][30] = {};
        for(int i = 0; i < M; i++){
            int K; cin >> K;
            while(K--){
                string s;
                cin >> s;
                have[i][ lang_dic[s] ] = true;
            }
        }

        vector<int> ans;

        bool b[30][30] = {};
        REP(i, N) REP(j, N) REP(k, M)
            b[i][j] |= have[k][i] & have[k][j];

        for(int K = 1; K < 6; K++){
            if(ans.size() > 0) break;
            int S = (1 << K) - 1;
            while(S < 1 << N){
                vector<int> v;
                for(int i = 0; i < N; i++) if(S >> i & 1) v.push_back(i);
                S = nextcomb(S);
                bool ok = true;

                REP(i, M) if(none_of(v.begin(), v.end(), [&](int vi){ return have[i][vi]; })) ok = false;

                if(not ok) continue;

                bool bb[30][30] = {};
                for(auto vi : v) for(auto vj : v) bb[vi][vj] = b[vi][vj];
                for(auto vk : v) for(auto vi : v) for(auto vj : v) bb[vi][vj] |= bb[vi][vk] & bb[vk][vj];

                REP(i, M) REP(j, i){
                    bool talk = false;
                    for(auto vi : v) for(auto vj : v) if(bb[vi][vj] && have[i][vi] && have[j][vj]){
                        goto NEXT;
                    }
                    ok = false;
                    goto NEXT2;

                    NEXT:;
                }

                if(ok) ans = v;
                NEXT2:;

            }
        }
        if(ans.empty()){
            cout << "Impossible" << endl;
            continue;
        }
        cout << ans.size() << endl;
        for(auto ai : ans){
            cout << lang[ai] << endl;
        }
    }
    return 0;
}
accuracy: 1
time_ms: 590
memory_kb: 1240
final_rank: 3

code_snippet: #include <iostream>
#include <algorithm>
#include <string>
#include <map>
#include <vector>
using namespace std;

const int MAXN = 50;
const int MAXM = 40;

class UnionFind {
private:
  int n;
  int *par, *rank;
public:
  UnionFind(int _n) {
    n = _n;
    par = new int[n];
    rank = new int[n];
    for(int i = 0; i < n; ++i) {
      par[i] = i;
      rank[i] = 0;
    }
  }

  ~UnionFind() {
    delete [] par;
    delete [] rank;
  }

  int find(int x) {
    if(par[x] == x) return x;
    return par[x] = find(par[x]);
  }

  bool same(int x, int y) {
    return find(x) == find(y);
  }

  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if(x == y) return;
    if(rank[x] < rank[y]) {
      par[x] = y;
    } else {
      par[y] = x;
      if(rank[x] == rank[y]) {
        ++rank[x];
      }
    }
  }
};

struct Edge {
  int a, b;
};

int N, M;
map<string, int> L;
vector<string> rL;
vector<int> S;
vector<int> V[6];
vector<Edge> E[MAXN];

void rec(int k, int i, int bit) {
  V[k].push_back(bit);
  if(k == 5) return;
  for(; i < N; ++i) {
    if(bit & (1<<i)) continue;
    rec(k+1, i+1, bit|(1<<i));
  }
}

bool test(int bit) {
  UnionFind uf(M);
  int cnt = 0;
  for(int i = 0; i < N; ++i) {
    if(bit & (1<<i)) {
      for(int j = 0; j < E[i].size(); ++j) {
        const Edge &e = E[i][j];
        if(!uf.same(e.a, e.b)) {
          uf.unite(e.a, e.b);
          ++cnt;
        }
      }
    }
  }
  return cnt == M-1;
}

int main() {
  bool first = true;
  while(cin >> N >> M && (N|M)) {
    L.clear();
    rL.clear();
    for(int i = 0; i < N; ++i) {
      string s;
      cin >> s;
      L[s] = L.size()-1;
      rL.push_back(s);
    }
    S = vector<int>(M, 0);
    for(int j = 0; j < M; ++j) {
      int k;
      cin >> k;
      while(k--) {
        string s;
        cin >> s;
        S[j] |= (1<<L[s]);
      }
    }
    for(int i = 0; i < 6; ++i) V[i].clear();
    rec(0,0,0);

    for(int i = 0; i < MAXN; ++i) E[i].clear();
    for(int a = 0; a < M; ++a) {
      for(int b = a+1; b < M; ++b) {
        int bit = (S[a] & S[b]);
        for(int k = 0; k < N; ++k) {
          if(bit & (1<<k)) {
            E[k].push_back((Edge){a,b});
          }
        }
      }
    }

    int ans = 0;
    try {
      for(int i = 1; i <= 5; ++i) {
        for(int j = 0; j < V[i].size(); ++j) {
          if(test(V[i][j])) {
            ans = V[i][j];
            throw 0;
          }
        }
      }
    } catch(...) {}

    if(first) first = false;
    else cout << endl;
    if(ans) {
      vector<string> v;
      for(int i = 0; i < N; ++i) {
        if(ans & (1<<i)) v.push_back(rL[i]);
      }
      cout << v.size() << endl;
      for(int i = 0; i < v.size(); ++i) {
        cout << v[i] << endl;
      }
    } else {
      cout << "Impossible" << endl;
    }
  }
  return 0;
}
accuracy: 1
time_ms: 490
memory_kb: 2468
final_rank: 8

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

class UnionFindTree
{
    int n;
    vector<int> parent; // 親ノード
    vector<int> rank;   // 木の高さの上限
    vector<int> num;    // グループの要素数
    int find(int x){
        if(parent[x] == x)
            return x;
        return parent[x] = find(parent[x]);
    }
public:
    UnionFindTree(int n0){ // コンストラクタ
        n = n0;
        parent.resize(n);
        for(int i=0; i<n; ++i)
            parent[i] = i;
        rank.assign(n, 0);
        num.assign(n, 1);
    }
    void unite(int x, int y){ // xとyのグループを併合
        if((x = find(x)) != (y = find(y))){
            if(rank[x] < rank[y]){
                parent[x] = y;
                num[y] += num[x];
            }else{
                parent[y] = x;
                if(rank[x] == rank[y])
                    ++ rank[x];
                num[x] += num[y];
            }
            -- n;
        }
    }
    bool same(int x, int y){ // xとyのグループが同じかを調べる
        return find(x) == find(y);
    }
    int getNum(){ // グループの数を返す
        return n;
    }
    int getNum(int x){ // xのグループの要素数を返す
        return num[find(x)];
    }
};

template <size_t T>
bool nextBitset(bitset<T> &bs, int digit)
{
    if(bs.none())
        return false;
    bitset<T> x, y, z;
    x = bs.to_ulong() & (~(bs.to_ulong()) + 1ULL);
    y = bs.to_ulong() + x.to_ulong() + 0ULL;
    z = bs & ~y;
    if(bs[digit-1] && bs == z)
        return false;
    bs = ((z.to_ulong() / x.to_ulong()) >> 1) + 0ULL;
    bs |= y;
    return true;
}

int n, m;
vector<string> name;
vector<bitset<30> > use;

void solve()
{
    for(int i=1; i<=min(5, n); ++i){
        bitset<30> bs((1<<i)-1);
        do{
            UnionFindTree uft(m);
            for(int j=0; j<m; ++j){
                for(int k=0; k<j; ++k){
                    if((use[j] & use[k] & bs).any())
                        uft.unite(j, k);
                }
            }

            if(uft.getNum() == 1){
                cout << i << endl;
                for(int j=0; j<n; ++j){
                    if(bs[j])
                        cout << name[j] << endl;
                }
                return;
            }
        }while(nextBitset(bs, n));
    }

    cout << "Impossible" << endl;
}

int main()
{
    bool isFirst = true;

    for(;;){
        cin >> n >> m;
        if(n == 0)
            return 0;

        name.resize(n);
        map<string, int> index;
        for(int i=0; i<n; ++i){
            cin >> name[i];
            index[name[i]] = i;
        }

        use.assign(m, 0);
        for(int i=0; i<m; ++i){
            int a;
            cin >> a;
            for(int j=0; j<a; ++j){
                string s;
                cin >> s;
                use[i][index[s]] = true;
            }
        }

        if(isFirst)
            isFirst = false;
        else
            cout << endl;

        solve();
    }
}
accuracy: 1
time_ms: 730
memory_kb: 1232
final_rank: 4