#define __USE_MINGW_ANSI_STDIO 0
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define endl '\n'
#define rep(i, a, b) for (int i = a; i < b; i++)
#define ff first
#define pii pair<int, int>
#define vii vector< pair<int,int> >
#define vi vector<int>
#define vvi vector< vector< int> >
#define ss second
#define mod 1000000007
#define pb push_back
#define mp make_pair
#define int long long
#define all(a) a.begin(), a.end()
#define inf (1LL<<61)
#define ull unsigned long long
#define trace1(x)                cout<<#x<<": "<<x<<endl
#define trace2(x, y)             cout<<#x<<": "<<x<<" | "<<#y<<": "<<y<<endl
#define trace4(x, y, z, d)          cout<<#x<<":" <<x<<" | "<<#y<<": "<<y<<" | "<<#z<<": "<<z<<" | "<<#d<<": "<<d<<endl

#define trace3(x, y, z)          cout<<#x<<":" <<x<<" | "<<#y<<": "<<y<<" | "<<#z<<": "<<z<<endl
#define debug1(x) cerr << #x << ": " << x <<'\n'
#define debug2(x, y) cerr << #x << ": " << x << '\t' << #y << ": " << y <<'\n'
#define debug3(x, y, z) cerr << #x << ": " << x << '\t' << #y << ": " << y << '\t' << #z << ": " << z <<'\n'
using namespace std;
//int dx[]={1,0,-1, 0};int dy[]={0,1,0, -1}; //4 Direction
//int dx[]={1,1,0,-1,-1,-1,0,1};int dy[]={0,1,1,1,0,-1,-1,-1};//8 direction
bool compare(const pair<pair<string,int>, int> &a,const pair<pair<string,int>, int> &b)
{
    if(a.ff.ff == b.ff.ff) {
        return (a.ff.ss > b.ff.ss);
    }
    return (a.ff.ff<b.ff.ff);
}
int poww(int a, int b)
{
    int res = 1;
    for(int i = 1; i<=b; ++i)
        res *= a;

    return res;
}
int findlcm(int arr[], int n) 
{ 
    // Initialize result 
    int ans = arr[0]; 
  
    // ans contains LCM of arr[0], ..arr[i] 
    // after i'th iteration, 
    for (int i = 1; i < n; i++) 
        ans = (((arr[i] * ans)) / 
                (__gcd(arr[i], ans))); 
  
    return ans; 
}
bool prime[100001];
void SieveOfEratosthenes(int n) 
{
    memset(prime, true, sizeof(prime));

    for (int p=2; p*p<=n; p++)
    {
        if (prime[p] == true)
        {
            for (int i=p*p; i<=n; i += p)
                prime[i] = false;
        }
  }
}

//Define mx for maximum range and MOD for large numbers
#define mx 100004
#define MOD 1000000007;
// Declare all the variables and global functions here - 
int n, m;
vi a[11];
vvi b;
void generateAllBinaryStrings(int n, int arr[], int i) 
{ 
    if (i == n) { 
    	vi temp;
    	rep(i, 0, n){
    		temp.pb(arr[i]);
    	}
    	b.pb(temp);
        return; 
    } 
  
    // First assign "0" at ith position 
    // and try for all other permutations 
    // for remaining positions 
    arr[i] = 0; 
    generateAllBinaryStrings(n, arr, i + 1); 
  
    // And then assign "1" at ith position 
    // and try for all other permutations 
    // for remaining positions 
    arr[i] = 1; 
    generateAllBinaryStrings(n, arr, i + 1); 
}
int32_t main()
{
    IOS;
 //    #ifndef ONLINE_JUDGE
 //    freopen("input.txt","r",stdin);
 //    freopen("output.txt","w",stdout);
	// #endif
    /********************* From here **********************/
    cin >> n >> m;
    rep(i, 0, m){
    	int k;
    	cin >> k;
    	rep(j, 0, k){
    		int s;
    		cin >> s;
    		a[i+1].pb(s);
    	}
    }
    int p[m];
    int arr[n];
    rep(i, 0, m){
    	cin >> p[i];
    }
    int ans = 0;
    generateAllBinaryStrings(n,arr,0 );
    rep(i,0,b.size()){
    	vi comb = b[i];
    	bool fg = true;
    	// rep(j, 0, comb.size()){
    	// 		cout << comb[j] << " ";
    	// }
    	// cout << endl;
    	rep(j, 0, m){
    		vi check = a[j+1];
    		int cnt = 0;
    		rep(k, 0, check.size()){
    			if(comb[check[k]-1] == 1 ){
    				cnt++;
    			}
    		}

    		if(cnt%2 != p[j]){
    			fg = false;
    			break;
    		}
    	}

    	
    	if(fg){
    		// rep(j, 0, comb.size()){
    		// 	cout << comb[j] << " ";
    		// }
    		// cout << endl;
    		ans++;
    	}
    	
    }

    cout << ans << endl;
    
    
}

Measured memory_bytes: 384