#include <bits/stdc++.h>
using namespace std;
const int maxn = 200000 + 10;
int n, m, ans[maxn], solved[maxn];
vector<pair<int, int> > edge[maxn];
int used[maxn], pos[maxn], marked[maxn], cnt[maxn];
void go_solve(int x, int q = -1) {
  solved[x] = true;
  for (int i = 0; i < edge[x].size(); ++i) {
    int y = edge[x][i].first;
    int p = edge[x][i].second;
    if (p == q)
      ans[p] = (used[p] == x ? (pos[p] == 1) : (pos[p] == -1));
    else if (!solved[y])
      go_solve(y, p);
  }
}
bool find_loop(int x, int fa) {
  marked[x] = 1;
  for (int i = 0; i < edge[x].size(); ++i) {
    int y = edge[x][i].first;
    int p = edge[x][i].second;
    if (fa == y) continue;
    if (marked[y]) {
      solved[x] = true;
      go_solve(x, p);
      return true;
    }
    if (find_loop(y, x)) return true;
  }
  return false;
}
void solve() {
  for (int i = 0; i < m; ++i)
    if (cnt[i] == 1) {
      solved[used[i]] = 1;
      ans[i] = (pos[i] == 1);
    }
  for (int i = 0; i < n; ++i)
    if (solved[i]) go_solve(i);
  for (int i = 0; i < n; ++i)
    if (!solved[i])
      if (!find_loop(i, -1)) {
        printf("NO\n");
        return;
      }
  printf("YES\n");
  for (int i = 0; i < m; ++i) printf("%d", ans[i] == 1);
  printf("\n");
}
int main() {
  memset(used, -1, sizeof(used));
  memset(ans, -1, sizeof(ans));
  scanf("%d%d", &n, &m);
  for (int i = 0; i < n; ++i) {
    int k;
    scanf("%d", &k);
    while (k--) {
      int y;
      scanf("%d", &y);
      int flag = y < 0 ? -1 : 1;
      y *= flag;
      --y;
      ++cnt[y];
      if (used[y] == -1) {
        used[y] = i;
        pos[y] = flag;
      } else {
        if (pos[y] == flag) {
          ans[y] = (flag == 1);
          solved[i] = 1;
          solved[used[y]] = 1;
        } else {
          edge[i].push_back(make_pair(used[y], y));
          edge[used[y]].push_back(make_pair(i, y));
        }
      }
    }
  }
  solve();
  return 0;
}
