#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
//typedef long double ld;

typedef map<int, int> mii;
typedef pair<int, int> pii;
typedef pair<double,double> pdd;
typedef set<int> si;
typedef set<ll> sll;
typedef vector<int> vi;
typedef vector<pair<int, int > > vii;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<vi> vvi;
typedef vector<vii> vvii;
typedef vector<vll> vvll;

constexpr ll MOD = 1e9+7;
constexpr int INF = 1<<30;
constexpr ll  LINF = 1LL<<60;

#define Sort(x) sort(x.begin(),x.end())
#define Reverse(x) reverse(x.begin(),x.end())
#define ABS(a,b) ((a)<(b)?(b)-(a):(a)-(b))
#define nbit(n) (1ll<<(n))

// sort(begin(x), end(x), greater<ll>());
// lower_bound(a.begin(), a.end(), val): a[i] ≥ valである最左の位置
// upper_bound(a.begin(), a.end(), val): a[i] > valである最左の位置

// Returns minimum of a and b.
// If a is less b, a is set to b.
template<typename T>
T chmin(T& a, T b) {
  if (a > b) {
    a = b;
  }
  return a;
}

// Returns maximum of a and b.
// If a is less b, a is set to b.
template<typename T>
T chmax(T& a, T b) {
  if (a < b) {
    a = b;
  }
  return a;
}

// a = (a+b)%MOD;
void addmod(ll& a, ll b) {
  a = (a+b)%MOD;
}

template <typename T>
void dumpContents(const T& v, const string& msg)
{
  cerr << "### " << msg << " ###\n";
  for (const auto& x : v) {
    cerr << x << " ";
  }
  cerr << endl;
}

struct before_main_function {
  before_main_function() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout<<setprecision(20)<<fixed;
    #define endl "\n"
  }
} before_main_function;

// x^y in O(log N)
ll pow_r(ll x, ll y) {
  assert(y>=0);

  ll ret = 1;
  while (y>0) {
    if (y%2) {
      ret = ret*x;
    }
    x *=x;
    y >>= 1;
  }

  return ret;
}



// mod pでのaの逆元
ll modinv(ll a, ll mod) {
  ll b = mod, u = 1, v = 0;
  while (b) {
      ll t = a/b;
      a -= t*b; swap(a, b);
      u -= t*v; swap(u, v);
  }
  u %= mod;
  if (u < 0) u += mod;
  return u;
}

// Matrix (m * n)
template<int MOD> struct Matrix {
    vector<vll> val; // column vectors
    const int M;
    const int N;

    Matrix(int m, int n, ll x = 0) :
      val(m, vll(n, x)), M(m), N(n) {}

    void init(int m, int n, ll x = 0) {
      val.assign(m, vll(n, x)), M(m), N(n);
    }

    // Return the number of rows
    size_t size() const {
      return val.size();
    }

    vll&       operator[](size_t i)       {return val[i];}
    const vll& operator[](size_t i) const {return val[i];}
};

template<int MOD> ostream& operator << (ostream& s, const Matrix<MOD>& A) {
  s << endl;
  for (int i=0; i<A.M; i++) {
    for (int j = 0; j < A.N; j++) {
      s << A[i][j] << ", ";
    }
    s << endl;
  }
  return s;
}

template<int MOD> Matrix<MOD> operator * (const Matrix<MOD>& A, const Matrix<MOD>& B) {
  assert(A.N == B.M);
  Matrix<MOD> R(A.M, B.N);

  for (int i = 0; i < A.M; i++)
    for (int j = 0; j < B.N; j++)
      for (int k = 0; k < B.M; k++)
        R[i][j] = (R[i][j] + A[i][k] * B[k][j] % MOD) % MOD;
  return R;
}

template<int MOD> Matrix<MOD> pow(const Matrix<MOD>& A, ull n) {
  assert(A.M == A.N);
  Matrix<MOD> R(A.M, A.M);

  for (int i = 0; i < A.size(); i++) R[i][i] = 1;

  while (n > 0) {
    if (n & 1ull) R = R * A;
    A = A * A;
    n >>= 1;
  }
  return R;
}

// Return rank of A.
//   rank: Aの値域の次元 <=> Aの列ベクトルが張る線型部分空間の次元
template<int MOD> int GaussJordan(Matrix<MOD>& A, bool is_extended = false) {
  for (int row=0; row<A.M; row++)
    for (int col=0; col<A.N; col++)
      A[row][col] = (A[row][col] % MOD + MOD) % MOD;

  int rank = 0;
  for (int col=0; col<A.N; col++) {
    if (is_extended && col == A.N-1) break;

    int pivot = -1;
    for (int row=rank; row<A.M; ++row) {
      if (A[row][col] != 0) {
        pivot = row;
        break;
      }
    }
    if (pivot == -1) continue;

    swap(A[pivot], A[rank]);
    auto inv = modinv(A[rank][col], MOD);

    // Make A[rank][col] be 1
    for (int col2=0; col2<A.N; col2++)
      A[rank][col2] = A[rank][col2] * inv % MOD;

    // 掃き出し
    for (int row=0; row<A.M; row++) {
      if (row != rank && A[row][col]) {
        auto fac = A[row][col];
        for (int col2=0; col2<A.N; col2++) {
          A[row][col2] -= A[rank][col2] * fac % MOD;
          if (A[row][col2] < 0) A[row][col2] += MOD;
        }
      }
    }
    rank++;
  }

  return rank;
}

// Ax = b
template<int MOD> int linear_equation(const Matrix<MOD>& A, vll b, vll &res) {
  Matrix<MOD> M(A.M, A.N+1);
  for (int i=0; i<A.M; i++) {
    for (int j=0; j<A.N; j++) {
      M[i][j] = A[i][j];
    }

    M[i][A.N] = b[i];
  }
  int rank = GaussJordan(M, true);

  // check if it has no solution
  for (int row=rank; row<A.M; row++) {
    if (M[row][A.N]) return -1;
  }

  // answer
  res.assign(A.N, 0);
  for (int i=0; i<rank; i++) res[i] = M[i][A.N];
  return rank;
}


// ========== end of template ==========

vvi sets;
vi ps;

int validate(const vi& switches) {
  for (int i=0; i<int(sets.size()); i++) {
    int x = 0;
    for (auto j : sets[i]) {
      x += switches[j];
    }
//cerr << "i " << i << ", x " << x <<endl;
    if (x%2 != ps[i]) {
      return 0;
    }
  }

  return 1;
};


int main(int argc, char** argv) {
  int N, M;
  cin >> N >> M;

  // mx=b において、mにbを入れたものを改めてmとする
  Matrix<2> m(M, N+1);

  for (int i=0; i<M; i++) {
    int k;
    cin >> k;
    for (int j=0; j<k; j++) {
      int x;
      cin >> x;
      x--; // 0-indexed

      m[i][x] = 1;
    }
  }

  for (int i=0; i<M; i++) {
    cin >> m[i][N];
  }

  int rank = GaussJordan(m, true);
cerr << "rank " << rank << endl;
  for (int row=rank; row<M; ++row) {
    if (m[row][N]) {
      cout << 0 << endl;
      return 0;
    }
  }

  int free = N-rank;

  cout << pow_r(2, free) << endl;

  return 0;
}


Measured memory_bytes: 256