Problem:
Score : 500 points

Problem Statement

We have N locked treasure boxes, numbered 1 to N.

A shop sells M keys. The i-th key is sold for a_i yen (the currency of Japan), and it can unlock b_i of the boxes: Box c_{i1}, c_{i2}, ..., c_{i{b_i}}. Each key purchased can be used any number of times.

Find the minimum cost required to unlock all the treasure boxes. If it is impossible to unlock all of them, print -1.

Constraints

All values in input are integers.

1 \leq N \leq 12

1 \leq M \leq 10^3

1 \leq a_i \leq 10^5

1 \leq b_i \leq N

1 \leq c_{i1} < c_{i2} < ... < c_{i{b_i}} \leq N

Input

Input is given from Standard Input in the following format:

N M
a_1 b_1
c_{11} c_{12} ... c_{1{b_1}}
:
a_M b_M
c_{M1} c_{M2} ... c_{M{b_M}}

Output

Print the minimum cost required to unlock all the treasure boxes.
If it is impossible to unlock all of them, print -1.

Sample Input 1

2 3
10 1
1
15 1
2
30 2
1 2

Sample Output 1

25

We can unlock all the boxes by purchasing the first and second keys, at the cost of 25 yen, which is the minimum cost required.

Sample Input 2

12 1
100000 1
2

Sample Output 2

-1

We cannot unlock all the boxes.

Sample Input 3

4 6
67786 3
1 3 4
3497 1
2
44908 3
2 3 4
2156 3
2 3 4
26230 1
2
86918 1
3

Sample Output 3

69942

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Numerics;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace debug
{
    class main
    {
        static void Main(string[] args)
        {
            //問題クラスを展開
            ProgramE a = new ProgramE();
            a.main();//実行する

        }

    }

    class ProgramA
    {
        public void main()
        {

            string input = Console.ReadLine();
            int a = int.Parse(input);

            //aが偶数のときは1/2、奇数のときは(a/2+1)/a
            if (a % 2 == 0)
                Console.WriteLine("0.5");
            else
                Console.WriteLine((double)((a / 2 + 1) / a));

        }
    }

    class ProgramB
    {
        public void main()
        {
            string[] input = Console.ReadLine().Split(' ');

            int n = int.Parse(input[0]);
            int k = int.Parse(input[1]);

            string[] a = Console.ReadLine().Split(' ');
            int count = 0;

            for (int i = 0; i < n; i++)
            {
                long ai = long.Parse(a[i]);
                if (k <= ai)
                    count++;

            }

            Console.WriteLine(count);
        }
    }

    class ProgramC
    {
        public void main()
        {

            string input = Console.ReadLine();
            int n = int.Parse(input);


            string[] input_b = Console.ReadLine().Split(' ');
            long[] b = new long[n];
            long[] c = new long[n];
            for (int i = 0; i < n; i++)
                b[i] = long.Parse(input_b[i]);


            for (int i = 1; i < n + 1; i++)
                c[b[i - 1] - 1] = i;

            for (int i = 0; i < n; i++)
                Console.Write(c[i] + " ");
        }
    }


    class ProgramD
    {
        public void main()
        {

            string[] input = Console.ReadLine().Split(' ');

            long a = long.Parse(input[0]);
            long b = long.Parse(input[1]);

            long c = gcd(a, b);//最大公約数を求める

            long count = prime(c);//素因数の数を求める
            

            Console.WriteLine(count);//答え出力

        }

        /*素因数分解したときの数を求める関数*/
        static long prime(long c)
        {
            long count = 1;//1はあらかじめカウント
            int flag = 0;

            //最大公約数が1なら答は1
            if (c == 1)
                return 1;

            //素因数分解してみる（例えば、2で割った後は2より大きい素数で2つの数で表せるかどうかを随時判定
            for (long i = 2; i <= Math.Sqrt(c); i++)
            {
                while (c % i == 0)
                {
                    c /= i;
                    flag = 1;
                }

                if (flag == 1)
                {
                    count++;
                    flag = 0;
                }

            }

            //ただし、計算結果でcが1以外ということは最後の素数が計上されていない。
            if (c != 1)
                count++;

            return count;
        }

        /*最大公約数を求める関数*/
        static long gcd(long p, long q)
        {
            if (p < q)
            {
                long temp = p;
                p = q;
                q = temp;
            }

            long r = 1;

            while (r != 0)
            {
                r = p % q;
                p = q;
                q = r;
            }

            return p;
        }

    }

    class ProgramE
    {
        public void main()
        {
            //入力
            string[] input = Console.ReadLine().Split(' ');
            int n= int.Parse(input[0]);
            int m = int.Parse(input[1]);

            //動的計画で記録しておく
            long[,] dp = new long[m, (1 << n)];
            long INF = 10000000000;

            //最初はINFを入れておく(未選択のみは入れない）
            for (int i = 0; i < m; i++)
                for (int j = 1; j < (1 << n); j++)
                    dp[i, j] = INF;


            int[,] treasure = new int[m, n];
            int[] a = new int[m];

            //動的計画を行う
            for (int i = 0; i < m; i++)
            {
                //読み込む
                string[] s = Console.ReadLine().Split(' ');
                a[i] = int.Parse(s[0]);
                //空けられるところを記録
                string[] key = Console.ReadLine().Split(' ');
                for (int j = 0; j < int.Parse(s[1]); j++)
                    treasure[i, int.Parse(key[j]) - 1] = 1;
            }

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

                for (int j = 0; j < (1 << n); j++)
                {
                    //一つ前が存在しないので検討しなくてよい
                    if (i != 0 && dp[i - 1, j] == INF)
                        continue;

                    //カギを使うときの数値を記録する
                    int num = 0;
                    for (int k = 0; k < n; k++)
                    {
                        if (treasure[i, k] == 1 || ((j >> k) & 1) == 1)
                            num += (int)Math.Pow(2, k);
                    }

                    //i= 0のときは基本何もしない（選んだ時だけ処理する）
                    if (i == 0)
                    {
                        dp[i, num] = a[i];
                        break;
                    }


                    //カギを使わないとき
                    dp[i, j] = Math.Min(dp[i - 1, j], dp[i, j]);
                    //カギを使うとき
                    dp[i, num] = Math.Min(dp[i, num], dp[i - 1, j] + a[i]);
                }

            }

            //INFだと-1それ以外は、答え出力する
            if (dp[m - 1, (1 << n) - 1] == INF)
                Console.WriteLine("-1");
            else
                Console.WriteLine(dp[m - 1, (1 << n) - 1]);

        }
    }


    
}