#include <bits/stdc++.h>
using namespace std;
const int N = 4 * 1e5 + 10;
bool NOTANS, HAS_CYCLE;
bool dor1[N], dor2[N];
int n, m, k, NUM_CYCLE;
pair<int, bool> setPar[N];
bool m1[N], m2[N], removed[N], mark[N], ans[N], seen[N], markingE[N];
vector<pair<int, bool> > e[N];
vector<pair<pair<int, int>, bool> > adj[N];
vector<pair<int, bool> > ej[N];
queue<int> q;
void dfs(int v, int par, int CC, bool NC) {
  markingE[CC] = 1;
  seen[v] = 1;
  if (par != -1) setPar[v] = {CC, !NC};
  for (int i = 0; i < adj[v].size(); i++) {
    int nv = adj[v][i].first.first;
    int cc = adj[v][i].first.second;
    int nc = adj[v][i].second;
    if (seen[nv]) continue;
    dfs(nv, v, cc, nc);
  }
}
void dfs1(int v, int par) {
  dor2[v] = dor1[v] = 1;
  for (int i = 0; i < adj[v].size(); i++) {
    int nv = adj[v][i].first.first;
    int nc = adj[v][i].first.second;
    if (dor2[nv] && !HAS_CYCLE && nc != par) {
      HAS_CYCLE = 1;
      NUM_CYCLE = nv;
    }
    if (dor1[nv]) continue;
    dor1[nv] = 1;
    dfs1(nv, nc);
  }
  dor2[v] = 0;
}
int main(int argc, const char* argv[]) {
  scanf("%d %d", &n, &m);
  for (int i = 1; i <= n; i++) {
    scanf("%d", &k);
    for (int j = 0; j < k; j++) {
      int u;
      scanf("%d", &u);
      bool flg = (u >= 0) ? 1 : 0;
      u = abs(u);
      u += n;
      if (flg)
        m1[u] = 1;
      else
        m2[u] = 1;
      ej[u].push_back({i, flg});
      ej[i].push_back({u, flg});
      e[u - n].push_back({i, flg});
    }
  }
  for (int i = n + 1; i <= n + m; i++)
    if (!m1[i] || !m2[i]) {
      q.push(i);
      mark[i] = 1;
    }
  while (!q.empty()) {
    int v = q.front();
    q.pop();
    bool isC = (v <= n) ? 1 : 0;
    if (isC)
      for (int i = 0; i < ej[v].size(); i++) {
        int nv = ej[v][i].first;
        if (mark[nv]) continue;
        mark[nv] = 1;
        q.push(nv);
      }
    else
      for (int i = 0; i < ej[v].size(); i++) {
        int nv = ej[v][i].first;
        bool cc = ej[v][i].second;
        if (mark[nv]) continue;
        mark[nv] = 1;
        q.push(nv);
        ans[v - n] = cc;
      }
  }
  for (int i = 1; i <= m; i++) {
    if (mark[i + n]) continue;
    int nv = i;
    int v1 = e[nv][0].first;
    bool c1 = e[nv][0].second;
    int v2 = e[nv][1].first;
    adj[v1].push_back({{v2, nv}, c1});
    adj[v2].push_back({{v1, nv}, !c1});
  }
  for (int i = 1; i <= n; i++)
    if (!seen[i] && !mark[i]) {
      dfs1(i, -1);
      if (!HAS_CYCLE) return cout << "NO", 0;
      dfs(NUM_CYCLE, -1, 0, 0);
      for (int j = 0; j < adj[NUM_CYCLE].size(); j++) {
        int nv = adj[NUM_CYCLE][j].first.second;
        bool cc = adj[NUM_CYCLE][j].second;
        if (!markingE[nv]) setPar[NUM_CYCLE] = {nv, cc};
      }
      NUM_CYCLE = 0;
      HAS_CYCLE = 0;
    }
  printf("YES\n");
  for (int i = 1; i <= n; i++) ans[setPar[i].first] = setPar[i].second;
  for (int i = 1; i <= m; i++) printf("%d", ans[i]);
  return 0;
}
