#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline T abs(T a) {
  return ((a < 0) ? -a : a);
}
template <typename T>
inline T sqr(T a) {
  return a * a;
}
const int N = (int)(2e5) + 10;
const int M = (int)(2e1) + 10;
const int logN = 22;
const int SQN = 350;
const int MOD = int(1e9) + 7;
const int INF = 1e9 + 100;
const long long INF_LL = 2e18;
const long long INF64 = 2e18;
const long double PI = 3.1415926535897932384626433832795;
const long double EPS = 1e-8;
int n, m;
int ans[N];
set<int> d[N];
int l[N], notl[N];
void solve() {
  memset(l, -1, sizeof l);
  memset(notl, -1, sizeof notl);
  cin >> n >> m;
  for (int i = 0; i < (int)(n); ++i) {
    int k;
    cin >> k;
    for (int j = 0; j < (int)(k); ++j) {
      int x;
      cin >> x;
      if (x > 0)
        l[x] = i;
      else
        notl[-x] = i;
      d[i].insert(x);
    }
  }
  set<pair<int, int> > s;
  for (int i = 0; i < (int)(n); ++i) s.insert(make_pair((int)(d[i].size()), i));
  while (!s.empty()) {
    pair<int, int> v = *s.begin();
    if ((int)(d[v.second].size()) == 0) {
      puts("NO");
      return;
    }
    int x = *d[v.second].begin();
    if (l[abs(x)] != -1) {
      if (s.count(make_pair((int)(d[l[abs(x)]].size()), l[abs(x)]))) {
        s.erase(make_pair((int)(d[l[abs(x)]].size()), l[abs(x)]));
        s.insert(make_pair((int)(d[l[abs(x)]].size()) - 1, l[abs(x)]));
        d[l[abs(x)]].erase(abs(x));
      }
    }
    if (notl[abs(x)] != -1) {
      if (s.count(make_pair((int)(d[notl[abs(x)]].size()), notl[abs(x)]))) {
        s.erase(make_pair((int)(d[notl[abs(x)]].size()), notl[abs(x)]));
        s.insert(make_pair((int)(d[notl[abs(x)]].size()) - 1, notl[abs(x)]));
        d[notl[abs(x)]].erase(-abs(x));
      }
    }
    s.erase(make_pair((int)(d[v.second].size()), v.second));
    ans[abs(x)] = (x > 0);
  }
  puts("YES");
  for (int i = 1; i <= m; ++i) cout << ans[i];
}
int main() {
  srand(time(NULL));
  cout << setprecision(10) << fixed;
  cerr << setprecision(10) << fixed;
  solve();
  return 0;
}
