//  [go]
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	io, flush := NewIO()
	defer flush()

	n, m := io.ScanInt2()

	var possibleCombinations [][]int
	for bit := 0; bit < (1 << uint(n)); bit++ {
		var comb []int
		for j := 0; j < n; j++ {
			if (bit>>uint(j))&1 == 1 {
				comb = append(comb, j+1)
			}
		}
		possibleCombinations = append(possibleCombinations, comb)
	}

	lightSwitchExistMap := map[int]map[int]bool{}
	for i := 0; i < m; i++ {
		k := io.ScanInt()
		lightSwitchExistMap[i] = map[int]bool{}
		for j := 0; j < k; j++ {
			lightSwitchExistMap[i][io.ScanInt()] = true
		}
	}

	mods := io.ScanInts(m)
	var count int
	for _, comb := range possibleCombinations {
		isValid := true
		for i := 0; i < m; i++ {
			var onCount int
			for _, s := range comb {
				if lightSwitchExistMap[i][s] {
					onCount++
				}
			}
			if onCount%2 != mods[i] {
				isValid = false
				break
			}
		}
		if isValid {
			count++
		}
	}
	fmt.Println(count)
}

// 1,2,5 (←のうちONが奇数だったら)
// 2,3 (←のうちONが偶数だったら)

// 1つずつ、ONになる組み合わせを全て出す
// 重複を消す
// その中から、全部の電球がONになるものだけ残す
//    - その組み合わせのスイッチがオンになっている
//    - その組み合わせのスイッチがオフの組み合わせに入っていない

type IO struct {
	scanner *bufio.Scanner
	writer  *bufio.Writer
}

func NewIO() (*IO, func()) {
	io := &IO{
		scanner: newScanner(),
		writer:  newWriter(),
	}
	return io, func() { io.writer.Flush() }
}

func newScanner() *bufio.Scanner {
	s := bufio.NewScanner(os.Stdin)
	s.Buffer(make([]byte, 10000000), 10000000)
	s.Split(bufio.ScanWords)
	return s
}

func newWriter() *bufio.Writer {
	return bufio.NewWriter(os.Stdout)
}

func (io *IO) ScanBytes() []byte {
	if !io.scanner.Scan() {
		panic("scan string failed")
	}
	return io.scanner.Bytes()
}

func (io *IO) ScanString() string {
	if !io.scanner.Scan() {
		panic("scan string failed")
	}
	return io.scanner.Text()
}

func (io *IO) ScanStrings(n int) []string {
	strs := make([]string, n)
	for i := 0; i < n; i++ {
		strs[i] = io.ScanString()
	}
	return strs
}

func (io *IO) Scan2DStrings(y, x int) [][]string {
	strings := make([][]string, y)
	for i := 0; i < y; i++ {
		strings[i] = io.ScanStrings(x)
	}
	return strings
}

func (io *IO) Scan2DGraph(y int) [][]string {
	strs := make([][]string, y)
	for i := 0; i < y; i++ {
		strs[i] = strings.Split(io.ScanString(), "")
	}
	return strs
}

func (io *IO) ScanInt() int {
	return int(io.ScanInt64())
}

func (io *IO) ScanInt2() (int, int) {
	return int(io.ScanInt64()), int(io.ScanInt64())
}

func (io *IO) ScanInt3() (int, int, int) {
	return int(io.ScanInt64()), int(io.ScanInt64()), int(io.ScanInt64())
}

func (io *IO) ScanInt4() (int, int, int, int) {
	return int(io.ScanInt64()), int(io.ScanInt64()), int(io.ScanInt64()), int(io.ScanInt64())
}

func (io *IO) ScanInts(n int) []int {
	ints := make([]int, n)
	for i := 0; i < n; i++ {
		ints[i] = io.ScanInt()
	}
	return ints
}

func (io *IO) Scan2DInts(y, x int) [][]int {
	ints := make([][]int, y)
	for i := 0; i < y; i++ {
		ints[i] = io.ScanInts(x)
	}
	return ints
}

func (io *IO) ScanInt64() int64 {
	i, err := strconv.ParseInt(io.ScanString(), 10, 64)
	if err != nil {
		panic(err)
	}
	return i
}

func (io *IO) ScanFloat64() float64 {
	i, _ := strconv.ParseFloat(io.ScanString(), 64)
	return i
}

func (io *IO) ScanFloat64s(n int) []float64 {
	floats := make([]float64, n)
	for i := 0; i < n; i++ {
		floats[i] = io.ScanFloat64()
	}
	return floats
}

func (io *IO) Println(a ...interface{}) {
	fmt.Fprintln(io.writer, a...)
}