#[allow(unused_imports)]
use proconio::input;
#[allow(unused_imports)]
use proconio::marker::{Chars, Usize1};
#[allow(unused_imports)]
use std::cmp::{max, min};
#[allow(unused)]
const ALPHA_SMALL: [char; 26] = [
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
    't', 'u', 'v', 'w', 'x', 'y', 'z',
];
#[allow(unused)]
const ALPHA: [char; 26] = [
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
    'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
];
#[allow(unused)]
fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}
#[allow(unused)]
fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>()
        .split_whitespace()
        .map(|e| e.parse().ok().unwrap())
        .collect()
}
#[allow(unused)]
fn read_touple<T: std::str::FromStr + Copy>() -> (T, T) {
    let v: Vec<T> = read_vec();
    assert_eq!(v.len(), 2);
    (v[0], v[1])
}

const INF: usize = 1_000_000_000 + 1000;
fn main() {
    input!(N: usize, M: usize);
    let mut keys = vec![(0usize, 0usize); M];
    for _ in 0..M {
        input!(a: usize, b: usize);
        input!(c: [Usize1; b]);
        let t = c.into_iter().fold(0, |acc, x| acc | (1 << x));
        keys.push((t, a));
    }
    let mut dp = vec![INF; (1 << N)];
    let bits = BitSet::empty(N);

    // init
    dp[0] = 0;
    for set in bits {
        let s = set.unwrap();
        for &(now, a) in &keys {
            let t = s | now;
            let cost = dp[s] + a;
            dp[t] = min(dp[t], cost);
        }
    }

    let mut ans = dp[(1 << N) - 1] as i64;
    if ans == INF as i64 {
        ans = -1;
    }

    println!("{}", ans);
}

#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
struct BitSet {
    bits: usize,
    size: usize,
}

impl std::fmt::Debug for BitSet {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "BitSet {{ bits: {:b}, size: {} }}", self.bits, self.size)
    }
}

impl BitSet {
    //
    fn empty(size: usize) -> BitSet {
        if size > 64 {
            panic!("large set size")
        }
        BitSet {
            bits: 0,
            size: size,
        }
    }
    // コンンストラクター
    fn new(n: usize, size: usize) -> BitSet {
        BitSet {
            bits: n,
            size: size,
        }
    }

    // 和集合を求める
    fn union(&self, other: BitSet) -> BitSet {
        BitSet {
            bits: self.bits | other.bits,
            size: self.size, // debug
        }
    }

    // 共通部分を求める
    fn intersect(&self, other: BitSet) -> BitSet {
        BitSet {
            bits: self.bits & other.bits,
            size: self.size, // debug
        }
    }

    // n を含むかどうか
    // n = 0, bits = 0b0001 => true
    // n = 1, bits = 0b0001 => false
    fn include(&self, n: usize) -> bool {
        if self.size < n {
            return false;
        }
        self.bits & (1 << n) != 0
    }

    // bitsをvectorに変換
    // 反転することに注意！
    // 0b0001 => vec![1, 0, 0, 0]
    // 0b1010 => vec![0, 1, 0, 1]
    fn to_vec(&self) -> std::vec::Vec<usize> {
        let mut res = std::vec::Vec::new();
        let mut bits = self.bits;

        for _ in 0..self.size {
            res.push(bits % 2);
            bits /= 2;
        }
        res
    }

    // 集合を表すusizeの値を返す
    fn unwrap(&self) -> usize {
        self.bits
    }
}

impl Iterator for BitSet {
    type Item = BitSet;

    fn next(&mut self) -> Option<Self::Item> {
        if (1 << self.size) <= self.bits {
            return None;
        }
        self.bits += 1;
        Some(BitSet {
            bits: self.bits - 1,
            size: self.size,
        })
    }
}


Measured memory_bytes: 2200