package main

import (
	"bufio"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)
var ans int = 0

func scanInt() int {
	num, _ := strconv.Atoi(scanString())
	return num
}

func scanString() string {
	sc.Scan()
	return sc.Text()
}

func scanInts(n int) []int {
	sl := make([]int, n)
	for i := range sl {
		sl[i] = scanInt()
	}
	return sl
}

func scanStrings(n int) []string {
	sl := make([]string, n)
	for i := range sl {
		sl[i] = scanString()
	}
	return sl
}

func init() {
	sc.Split(bufio.ScanWords)
}

func check(now []bool, next_idx int, N int, data map[int][]int, correct []bool) {
	// if index N is on
	now_on := make([]bool, len(now))
	now_off := make([]bool, len(now))
	copy(now_on, now)
	copy(now_off, now)

	if _, ok := data[next_idx]; ok {
		for _, i := range data[next_idx] {
			now_on[i-1] = !now_on[i-1]
		}
	}
	ok := true
	for i := range now_on {
		if correct[i] != now_on[i] {
			ok = false
			break
		}
	}
	if ok == true {
		ans++
	}

	if next_idx == 1 {
		ok := true
		for i := range now_off {
			if correct[i] != now_off[i] {
				ok = false
				break
			}
		}
		if ok == true {
			ans++
		}
	}

	//fmt.Printf("%v => %v %v\n", now, now_on, now_off)
	if next_idx != N {
		// if index N is off
		check(now_off, next_idx+1, N, data, correct)
		check(now_on, next_idx+1, N, data, correct)
	}
}

func main() {
	N, M := scanInt(), scanInt()
	data := map[int][]int{}
	for i := 0; i < M; i++ {
		k := scanInt()
		for j := 0; j < k; j++ {
			s := scanInt()
			if _, ok := data[s]; ok {
				data[s] = append(data[s], i+1)
			} else {
				data[s] = []int{i + 1}
			}
		}
	}
	//fmt.Printf("%v\n", data)
	correct := make([]bool, M)
	for i := 0; i < M; i++ {
		if scanInt() == 0 {
			correct[i] = false
		} else {
			correct[i] = true
		}
	}
	state := make([]bool, M)
	//fmt.Printf("init: %v\n", state)
	check(state, 1, N, data, correct)
	println(ans)
}
