#include <bits/stdc++.h>
using namespace std;
int clause_p[200010], clause_n[200010], resp[200010], ended[200010],
    cor[200010], cor2[200010], varpai[200010];
vector<pair<int, int> > adj[200010];
int incycle;
bool cycle;
void dfs(int u) {
  cor[u] = 1;
  ended[u] = 1;
  int tam = adj[u].size();
  for (int i = 0; i < tam; i++) {
    int v = adj[u][i].first, var = adj[u][i].second;
    if (resp[var] == -1) {
      if (v == clause_n[var]) {
        resp[var] = 0;
      } else {
        resp[var] = 1;
      }
    }
    if (cor[v] == 0) {
      dfs(v);
    }
  }
  cor[u] = 2;
}
void dfs2(int u) {
  cor[u] = 1;
  int tam = adj[u].size();
  for (int i = 0; i < tam; i++) {
    int v = adj[u][i].first, var = adj[u][i].second;
    if (!ended[v]) {
      if (cor[v] == 0) {
        varpai[v] = var;
        dfs2(v);
      } else if (cor[v] == 1 && var != varpai[u]) {
        cycle = true;
        incycle = v;
      }
    }
  }
  cor[u] = 2;
}
void dfs_fill(int u) {
  cor2[u] = 1;
  int tam = adj[u].size();
  for (int i = 0; i < tam; i++) {
    int v = adj[u][i].first, var = adj[u][i].second;
    if (!ended[v]) {
      if (resp[var] == -1) {
        if (v == clause_n[var]) {
          resp[var] = 0;
        } else {
          resp[var] = 1;
        }
      }
      if (cor2[v] == 0) {
        dfs_fill(v);
      }
    }
  }
  cor2[u] = 2;
}
int main() {
  int cla, var, k, x;
  while (scanf("%d %d", &cla, &var) != EOF) {
    memset(clause_p, -1, sizeof(clause_p));
    memset(clause_n, -1, sizeof(clause_n));
    memset(ended, 0, sizeof(ended));
    memset(resp, -1, sizeof(resp));
    for (int i = 0; i < cla; i++) {
      adj[i].clear();
      scanf("%d", &k);
      for (int j = 0; j < k; j++) {
        scanf("%d", &x);
        if (x > 0) {
          x--;
          if (clause_p[x] != -1) {
            ended[i] = 1;
            ended[clause_p[x]] = 1;
          }
          clause_p[x] = i;
        } else {
          x = -x;
          x--;
          if (clause_n[x] != -1) {
            ended[i] = 1;
            ended[clause_n[x]] = 1;
          }
          clause_n[x] = i;
        }
      }
    }
    for (int i = 0; i < var; i++) {
      if (clause_p[i] == -1 && clause_n[i] == -1) {
        resp[i] = 0;
      } else if (clause_p[i] == -1) {
        ended[clause_n[i]] = 1;
        resp[i] = 0;
      } else if (clause_n[i] == -1) {
        ended[clause_p[i]] = 1;
        resp[i] = 1;
      } else {
        adj[clause_p[i]].push_back(pair<int, int>(clause_n[i], i));
        adj[clause_n[i]].push_back(pair<int, int>(clause_p[i], i));
      }
    }
    memset(cor, 0, sizeof(cor));
    for (int i = 0; i < cla; i++) {
      if (ended[i] && cor[i] == 0) {
        dfs(i);
      }
    }
    memset(cor, 0, sizeof(cor));
    memset(cor2, 0, sizeof(cor2));
    bool possible = true;
    for (int i = 0; i < cla; i++) {
      cycle = false;
      if (!ended[i] && cor[i] == 0) {
        dfs2(i);
        if (cycle == false) {
          possible = false;
        } else {
          dfs_fill(incycle);
        }
      }
    }
    if (!possible) {
      printf("NO\n");
      continue;
    } else {
      printf("YES\n");
      for (int i = 0; i < var; i++) {
        printf("%d", resp[i]);
      }
      printf("\n");
    }
  }
  return 0;
}
