#include <bits/stdc++.h>
#include <cstdio>
using namespace std;
 
typedef long long ll;
typedef unsigned long long ull;
 
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(b)-1;i>=(a);i--)
#define REP(i,n) for(int i=0;i<(n);i++)
#define RREP(i,n) for(int i=(n)-1;i>=0;i--)
#define VSORT(v) sort(v.begin(), v.end())
#define SORT(v, n) sort(v, v+n)
#define VREV(v) reverse(v.begin(),v.end())
#define REV(v,n) reverse(v,v+n)
#define vi vector<int>
#define pf push_front
#define pb push_back

template<class T, size_t N> size_t countof(const T (&array)[N]) { return N; }
template <class T> void chmin(T&a,const T&b) { a = min(a,b); }
template <class T> void chmax(T&a,const T&b) { a = max(a,b); }
 
void print(){cout<<"\n";}
template <class Head, class... Tail>
void print(Head&& h,Tail&&... t){ 
	if(sizeof...(t)==0)
		cout<<h;
	else
		cout<<h<<' ';
	print(move(t)...);
}

void mprint(auto *matrix,auto N){
	REP(i,N) cout<<matrix<<(i!=N-1?' ':'\n');
	return;
}

const double EPS =1e-9;
const int INF =2e+9;
const ll INFL =9e+18;
const long MOD =1e+9+7;
#define PI 3.14159265258979

#define P pair<int,int>
#define Pll pair<ll,ll>
int dy[]={0, 0, 1, -1, 1, 1, -1, -1};
int dx[]={1, -1, 0, 0, 1, -1, -1, 1};

inline int in(){int x; cin>>x; return x;}

struct UnionFind{
	vector<int> par; //データiが属する親の番号
	vector<int> sizes; //根ノードiの木に含まれるデータの数

	// 最初は全てのデータiがグループiに存在するものとして初期化
	UnionFind(int n):par(n),sizes(n, 1){
		REP(i,n) par[i] = i;
	}

	// 根を張り替えながら再帰的に根ノードを探す
	int find(int x){
		if(x==par[x]) return x;
		return par[x]=find(par[x]);
	}

	// 2つのデータx, yが属する木をマージする
	void unite(int x, int y) {
		// データの根ノードを得る
		x = find(x);
		y = find(y);

		// 既に同じ木に属しているならマージしない
		if (x == y) return;

		// xの木がyの木より大きくなるようにする
		if (sizes[x] < sizes[y]) swap(x, y);

		// xがyの親になるように連結する
		par[y] = x;
		sizes[x] += sizes[y];
		sizes[y] = 0;  // sizes[y]は無意味な値となるため
	}

	// 2つのデータx, yが属する木が同じならtrueを返す
	bool same(int x, int y) {
		return find(x) == find(y);
	}

	// データxが含まれる木の大きさを返す
	int size(int x) {
		return sizes[find(x)];
	}
};
int gcd(int n,int m){
	if(m>n) return gcd(m,n);
	if(m==0) return n;
	else return gcd(m,n%m); 
}

int main(void){
	int N,M,k,s,p[10];
	set<int> S[10];

	cin>>N>>M;
	REP(i,N){
		cin>>k;
		REP(j,k){
			cin>>s;
			S[i].insert(s);
		}
	}
	REP(i,M) cin>>p[i];

	int result=0,count=0;
	bool flug=false;
	REP(i,pow(2,N)){
		flug=true;

		stringstream ss;
		ss << static_cast<std::bitset<12>>(i);
		string tem=ss.str();
		reverse(tem.begin(), tem.end());;
		
		REP(j,M){
			count=0;
			REP(r,N)
				if(tem[r]=='1' && S[j].count(r+1)==1) count++;
			
			
			if(count%2!=p[j]){
				flug=false;
				break;
			}
		}
		if(flug) result++;
	}
	print(result);
	return 0;
}
