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# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Numerics;
using System.Threading;
using System.Runtime.CompilerServices;
using System.Diagnostics;
using static System.Math;
using static System.Array;
using static AtCoder.Cout;
using static AtCoder.Tool;
using static AtCoder.ModInt;
namespace AtCoder
{
    class AC
    {
        const int MOD = 1000000007;
        //const int MOD = 998244353;
        const int INF = int.MaxValue / 2;
        const long SINF = long.MaxValue / 3;
        const double EPS = 1e-8;
        static readonly int[] dI = { 0, 1, 0, -1, 1, -1, -1, 1 };
        static readonly int[] dJ = { 1, 0, -1, 0, 1, 1, -1, -1 };
        static void Main(string[] args)
        {
            //var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false }; Console.SetOut(sw);

            var th = new Thread(Run, 1 << 26);
            th.Start();
            th.Join();

            //Run();
            Console.Out.Flush();
        }
        static void Run()
        {
            int Testcase = 1;
            //Testcase = Cin.Int;
            for (var _ = 0; _ < Testcase; _++) Solve();
        }
        static void Solve()
        {
            Cin.Scanf(out int N, out int M);
            var dp = new long[(1 << N)];
            Fill(dp, INF);
            dp[0] = 0;
            for(var i = 0; i < M; i++)
            {
                Cin.Scanf(out int a, out int b);
                var c = Cin.ReadSplitInt;
                int m = 0;
                for (var j = 0; j < b; j++) m |= (1 << (c[j] - 1));
                var dp2 = new long[(1 << N)];
                Fill(dp2, INF);
                for(var j = 0; j < (1 << N); j++)
                {
                    dp2[j] = Min(dp2[j], dp[j]);
                    dp2[j | m] = Min(dp2[j | m], dp[j] + a);
                }
                dp = dp2;
            }
            OutL(dp[(1 << N) - 1] == INF ? -1 : dp[(1 << N) - 1]);
        }
        
        public struct Edge
        {
            public int from;

            public int to;
            public long dist;

            public Edge(int t, long c)
            {
                from = -1;
                to = t;
                dist = c;
            }
            public Edge(int f, int t, long c)
            {
                from = f;
                to = t;
                dist = c;
            }
        }
    }
    struct ModInt
    {
        public long value;
        private const int MOD = 1000000007;
        //private const int MOD = 998244353;
        public ModInt(long value) { this.value = value; }
        public static implicit operator ModInt(long a)
        {
            var ret = a % MOD;
            return new ModInt(ret < 0 ? (ret + MOD) : ret);
        }
        public static ModInt operator +(ModInt a, ModInt b) => (a.value + b.value);
        public static ModInt operator -(ModInt a, ModInt b) => (a.value - b.value);
        public static ModInt operator *(ModInt a, ModInt b) => (a.value * b.value);
        public static ModInt operator /(ModInt a, ModInt b) => a * Modpow(b, MOD - 2);

        public static ModInt operator <<(ModInt a, int n) => (a.value << n);
        public static ModInt operator >>(ModInt a, int n) => (a.value >> n);
        public static ModInt operator ++(ModInt a) => a.value + 1;
        public static ModInt operator --(ModInt a) => a.value - 1;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static ModInt Modpow(ModInt a, long n)
        {
            if (n < 0) return Modpow(Modpow(a, -n), MOD - 2);
            var k = a;
            ModInt ret = 1;
            while (n > 0)
            {
                if ((n & 1) != 0) ret *= k;
                k *= k;
                n >>= 1;
            }
            return ret;
        }
        private static readonly List<long> Factorials = new List<long>() { 1 };
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static ModInt Fac(long n)
        {
            for (var i = Factorials.Count(); i <= n; i++)
            {
                Factorials.Add((Factorials[i - 1] * i) % MOD);
            }
            return Factorials[(int)n];
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static ModInt nCr(long n, long r)
        {
            if (n < 0 || r < 0) return 0;
            return n < r ? 0 : Fac(n) / (Fac(r) * Fac(n - r));
        }
        public static explicit operator int(ModInt a) => (int)a.value;
    }
    public class Rolling_Hash
    {
        const ulong m30 = (1UL << 30) - 1;
        const ulong m31 = (1UL << 31) - 1;
        const ulong MOD = (1UL << 61) - 1;
        const ulong Pl = (MOD << 1) << 1;
        private uint B;
        private string S;
        ulong[] hash;
        ulong[] pw;

        public Rolling_Hash(string str)
        {
            S = str;
            B = (uint)new Random().Next(1 << 12 + 1, int.MaxValue);
            int L = S.Length;
            hash = new ulong[L + 1];
            pw = new ulong[L + 1];
            hash[0] = 0;
            pw[0] = 1;
            for (var i = 0; i < L; i++)
            {
                hash[i + 1] = CalcMod(Mul(hash[i], B) + S[i]);
                pw[i + 1] = CalcMod(Mul(pw[i], B));
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public ulong GetHashValue(int idx) => hash[idx];
        [MethodImpl(MethodImplOptions.AggressiveInlining)]//segment [l,r]
        public ulong Hash_fold(int l, int r) => CalcMod(Pl + hash[r + 1] - Mul(hash[l], pw[r - l + 1]));
        [MethodImpl(MethodImplOptions.AggressiveInlining)]//segment[start,start+len-1]
        public ulong Hash_sub(int start, int len) => CalcMod(Pl + hash[start + len] - Mul(hash[start], pw[len]));
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public ulong[] GetHashArray() => hash;

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        ulong Mul(ulong a, ulong b)
        {
            ulong au = a >> 31;
            ulong ad = a & m31;
            ulong bu = b >> 31;
            ulong bd = b & m31;
            ulong mid = ad * bu + au * bd;
            ulong midu = mid >> 30;
            ulong midd = mid & m30;
            return au * bu * 2 + midu + (midd << 31) + ad * bd;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        ulong CalcMod(ulong x)
        {
            ulong xu = x >> 61;
            ulong xd = x & MOD;
            ulong res = xu + xd;
            if (res >= MOD) res -= MOD;
            return res;
        }
    }
    public class Priority_Queue<T>
    {
        private List<T> Q;
        private readonly Comparison<T> Func_Compare;
        public Priority_Queue(Comparison<T> comp)
        {
            Func_Compare = comp;
            Q = new List<T>();
        }
        private void PushHeap(List<T> list, T item)
        {
            int n = list.Count();
            list.Add(item);

            while (n != 0)
            {
                int pIndex = (n - 1) / 2;

                if (Func_Compare(list[n], list[pIndex]) < 0)
                {
                    Swap(Q, n, pIndex);
                }
                else { break; }

                n = pIndex;
            }
        }
        private void PopHeap(List<T> list)
        {
            int n = list.Count() - 1;
            list[0] = list[n];
            list.RemoveAt(n);

            int cur = 0;
            int comp;

            while (2 * cur + 1 <= n - 1)
            {
                int c1 = 2 * cur + 1;
                int c2 = 2 * (cur + 1);
                if (c1 == n - 1)
                {
                    comp = c1;
                }
                else
                {

                    comp = Func_Compare(list[c1], list[c2]) < 0 ? c1 : c2;
                }

                if (Func_Compare(list[cur], list[comp]) > 0)
                {
                    Swap(Q, cur, comp);
                }
                else { break; }

                cur = comp;
            }
        }
        private void Swap(List<T> list, int a, int b)
        {
            T keep = list[a];
            list[a] = list[b];
            list[b] = keep;
        }

        public void Enqueue(T value)
        {
            PushHeap(Q, value);
        }

        public T Dequeue()
        {
            T ret = Q[0];
            PopHeap(Q);
            return ret;
        }

        public T Peek()
        {
            return Q[0];
        }

        public int Count()
        {
            return Q.Count();
        }
        public bool Any()
        {
            return Q.Any();
        }
    }
    public class SegmentTree<T>
    {
        //1-indexed type
        int n;
        T[] Tree;
        Func<T, T, T> f;
        T ex;
        int L;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public SegmentTree(int size, Func<T, T, T> fun, T exvalue)
        {
            ex = exvalue;
            f = fun;
            n = 1;
            while (n < size) n <<= 1;
            Tree = new T[n << 1];
            L = (n << 1) - 1;
            for (var i = 0; i <= L; i++) Tree[i] = ex;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public SegmentTree(int size, Func<T, T, T> fun, T exvalue, T[] initial)
        {
            ex = exvalue;
            n = 1; while (n < size) n <<= 1;
            f = fun;
            Tree = new T[n << 1];
            L = (n << 1) - 1;
            for (var i = 0; i <= L; i++) Tree[i] = (n <= i && i <= n + initial.Length - 1) ? initial[i - n] : ex;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Set_All()
        {
            for (var i = n - 1; i >= 1; i--) Tree[i] = f(Tree[i << 1], Tree[(i << 1) | 1]);
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Assign(int idx, T nxt) => Tree[idx + n] = nxt;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Update(int idx)
        {
            int now = idx + n;
            while (now > 1)
            {
                now >>= 1;
                Tree[now] = f(Tree[now << 1], Tree[now << 1 | 1]);
            }
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Query_Update(int idx, T nxt)
        {
            Assign(idx, nxt); Update(idx);
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Query_Update_func(int idx, T y)
        {
            Assign(idx, f(Peek(idx), y)); Update(idx);
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public T Query_Fold(int l, int r)
        {
            int L = n + l;
            int R = n + r;
            T vL = ex, vR = ex;
            while (L < R)
            {
                if (L % 2 == 1)
                {
                    vL = f(vL, Tree[L]);
                    L++;
                }
                if (R % 2 == 1)
                {
                    vR = f(Tree[R - 1], vR);
                    R--;
                }
                L >>= 1;
                R >>= 1;
            }
            return f(vL, vR);
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public T Peek(int idx) => Tree[idx + n];
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Display(int len)
        {
            for (var i = 0; i < len; i++) Console.Write($"{Tree[i + n]} ");
            Console.WriteLine();
        }
    }
    public class UnionFind
    {
        private int[] parent;
        private int[] rank;
        private int[] size;
        public UnionFind(int n)
        {
            parent = new int[n];
            rank = new int[n];
            size = new int[n];
            for (var i = 0; i < n; i++)
            {
                parent[i] = i;
                rank[i] = 0;
                size[i] = 1;
            }
        }

        public int Root(int x)
        {
            return parent[x] == x ? x : parent[x] = Root(parent[x]);
        }

        public bool SameRoot(int x, int y)
        {
            return Root(x) == Root(y);
        }

        public void Unite(int x, int y)
        {
            x = Root(x);
            y = Root(y);
            if (x == y) { return; }

            if (rank[x] < rank[y])
            {
                parent[x] = y;
                size[y] += size[x];
                size[x] = 0;
            }
            else
            {
                parent[y] = x;
                if (rank[x] == rank[y]) { rank[x]++; }
                size[x] += size[y];
                size[y] = 0;
            }
        }

        public int SizeOf(int x)
        {
            return size[Root(x)];
        }

    }
    static class Cin
    {
        public static string[] ReadSplit => Console.ReadLine().Split();
        public static int[] ReadSplitInt => ConvertAll(Console.ReadLine().Split(), int.Parse);
        public static long[] ReadSplitLong => ConvertAll(Console.ReadLine().Split(), long.Parse);
        public static double[] ReadSplit_Double => ConvertAll(Console.ReadLine().Split(), double.Parse);
        public static string Str => Console.ReadLine();
        public static int Int => int.Parse(Console.ReadLine());
        public static long Long => long.Parse(Console.ReadLine());
        public static double Double => double.Parse(Console.ReadLine());
        public static T Conv<T>(string input)
        {
            if (typeof(T).Equals(typeof(ModInt)))
            {
                return (T)(dynamic)(long.Parse(input));
            }
            return (T)Convert.ChangeType(input, typeof(T));
        }
        public static void Scanf<T>(out T a) => a = Conv<T>(Console.ReadLine());
        public static void Scanf<T, U>(out T a, out U b)
        { var q = ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); }
        public static void Scanf<T, U, V>(out T a, out U b, out V c)
        { var q = ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); c = Conv<V>(q[2]); }
        public static void Scanf<T, U, V, W>(out T a, out U b, out V c, out W d)
        { var q = ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); c = Conv<V>(q[2]); d = Conv<W>(q[3]); }
        public static void Scanf<T, U, V, W, X>(out T a, out U b, out V c, out W d, out X e)
        { var q = ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); c = Conv<V>(q[2]); d = Conv<W>(q[3]); e = Conv<X>(q[4]); }
    }
    static class Cout
    {
        public static void OutL(object s) => Console.WriteLine(s);
        public static void Out_Sep<T>(IEnumerable<T> s) => Console.WriteLine(string.Join(" ", s));
        public static void Out_Sep<T>(IEnumerable<T> s, string sep) => Console.WriteLine(string.Join($"{sep}", s));
        public static void Out_Sep(params object[] s) => Console.WriteLine(string.Join(" ", s));
        public static void Out_One(object s) => Console.Write($"{s} ");
        public static void Out_One(object s, string sep) => Console.Write($"{s}{sep}");
        public static void Endl() => Console.WriteLine();
    }
    public static class Tool
    {
        static public void Initialize<T>(ref T[] array, T initialvalue)
        {
            array = ConvertAll(array, x => initialvalue);
        }
        static public void Swap<T>(ref T a, ref T b)
        {
            T keep = a;
            a = b;
            b = keep;
        }
        static public void Display<T>(T[,] array2d, int n, int m)
        {
            for (var i = 0; i < n; i++)
            {
                for (var j = 0; j < m; j++)
                {
                    Console.Write($"{array2d[i, j]} ");
                }
                Console.WriteLine();
            }
        }
        static public long Gcd(long a, long b)
        {
            if (a == 0 || b == 0) return Max(a, b);
            return a % b == 0 ? b : Gcd(b, a % b);
        }
        static public long LPow(int a, int b) => (long)Pow(a, b);
        static public bool Bit(long x, int dig) => ((1L << dig) & x) != 0;
        static public int Sig(long a) => a == 0 ? 0 : (int)(a / Abs(a));
    }
}