#include <iostream>
#include <math.h>
#include <numeric>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <queue>
#include <queue>
#include <sstream>
#include <set>
typedef  long long ll;
const int dx[8]={1,0,-1,0,1,-1,-1,1};
const int dy[8]={0,1,0,-1,1,1,-1,-1};
const int dr[4] = {-1, 0, 1, 0};
const int dc[4] = { 0, 1, 0,-1};
const int INF = 1e9;
#define FOR(i, a, n) for(int i = (int)(a); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define SORT(a) sort(a.begin(),a.end())
#define REVERSE(a) reverse(a.begin(),a.end())
int guki (int a){
    if(a%2==0) return 0;
    else return 1;
}
int gcd(int a, int b){
    if(a%b==0){
        return b;
    }else{
        return (gcd(b,a%b));
    }
}
int lcm(int a, int b){
    int x = gcd(a,b);
    return (a*b/x);
}
using namespace std;
int main(){
   ll n,m;
   cin >> n >> m;
   vector<vector<ll> v(m);
   REP(i,m){
       ll k;
       cin >> k;
       v[i].resize(k);
       REP(j,k){
           cin >> v[i][j];
           v[i][k] --;
       }
   }

   vector<ll> p(m);
   REP(i,m){
       cin >> p[i];
   }

   ll ans = 0;
   REP(i, (1 << n)){
       vector<ll> f(n);
       REP(j, n){
           if(i & (1<<j)){
               f[j] = true;
           }
       }

       bool ok = true;

       REP(j,m){
           ll cnt = 0;
           REP(k, v[j].size()){
               if(f[v[j][k]]) cnt ++;
           }
           if(cnt %2 != p[j]){
               ok = false;
               break;
           }
       }
       if(ok) ans ++;
   }
   cout << ans <<endl;
}