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 Ki that indicates the number of languages the i-th student speaks, and
Ki 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

Solution in C (judge verdict: Accepted)

// AOJ 2061: International Party
// 2017.11.8 bal4u@uu

#include <stdio.h>
#include <string.h>
#define TM 0
#if TM
#include <time.h>
#endif

#define HASHSIZ 61
typedef struct { char *s; int id; } HASH;
HASH hash[HASHSIZ+2], *hashend = hash+HASHSIZ;			// Hash table

int lookup(char *s)
{
	int w = strlen(s);
	int i = (101 * *s + 103 * *(s+w-1) + 107 * w) % HASHSIZ;
	HASH *tp = hash + i;

	while (tp->s != NULL) {
		if (!strcmp(tp->s, s)) return tp->id;
		if (++tp == hashend) tp = hash;
	}
	return -1;
}

int insert(char *s, int id)
{
	int w = strlen(s);
	int i = (101 * *s + 103 * *(s+w-1) + 107 * w) % HASHSIZ;
	HASH *tp = hash + i;

	while (tp->s != NULL) {
		if (!strcmp(tp->s, s)) return 0;
		if (++tp == hashend) tp = hash;
	}
	tp->s = s, tp->id = id;
	return 1;
}

int f[22], m;
char name[31][22]; int sz;

int check(int pat)
{
	int i, j, k, s;
	int g[6];

	for (i = 0; i < m; i++) {
		if (!(f[i] & pat)) return 0;
	}

	for (s = 0, k = pat, i = 0; k; i++, k >>= 1) if (k & 1) g[s++] = 1 << i;  
	for (i = 0; i < m; i++) {
		for (j = 0; j < s; j++) {
			if (g[j] & f[i]) g[j] |= f[i] & pat;
		}
	}
	for (k = g[0], i = 1; i < s; i++) if (g[i] & k) k |= g[i]; 
	return k == pat;
}

int main()
{
	int cno = 0, n, i, j, id, ans;
	char buf[22];
#if TM
	clock_t start, end;
	start = clock();
#endif

	while (scanf("%d%d", &n, &m) && n > 0) {
		if (cno++ > 0) putchar('\n');
		memset(hash, 0, sizeof(hash));
		memset(f, 0, sizeof(f));

		id = 1, sz = 0;
		while (n--) {
			scanf("%s", name[sz]);
			if (insert(name[sz], id)) sz++, id <<= 1;
		}

		for (i = 0; i < m; i++) {
			scanf("%d", &j);
			while (j--) {
				scanf("%s", buf);
				id = lookup(buf);
				f[i] |= id;
			}
		}

		ans = -1;
		for (i = 1; i <= 5; i++) {
			for (j = (1 << i) - 1; j < (1 << sz); ) {
				int x, y;
				if (check(j)) { ans = j, id = i; goto done; }
				x = j & ~(j - 1);
				y = j + x;
				j = (((j & ~y) / x) >> 1) | y;
			}
		}
done:	if (ans < 0) puts("Impossible");
		else {
			printf("%d\n", id);
			for (id = 1, i = 0; i < sz; i++, id <<= 1) {
				if (ans & id) puts(name[i]);
			}
		}
	}
#if TM
	end = clock();
	printf("time %lf\n", (double)(end-start)/CLOCKS_PER_SEC);
#endif
	return 0;
}