#include <bits/stdc++.h>
using namespace std;
using ns = chrono::nanoseconds;
using get_time = chrono::steady_clock;
int n, m;
int curPos = 0;
vector<vector<int>> data;
vector<int> groups;
vector<bool> visited(200010, false);
vector<int> res(200010, -1);
vector<pair<int, int>> mapToGroup(200010, {0, 0});
vector<int> nNode(200010, 0);
int findTheOtherEndGroup(int group, int var) {
  pair<int, int> info = mapToGroup[abs(var)];
  if (abs(info.first) == group) return info.second;
  if (abs(info.second) == group) return info.first;
}
int findHalfBridge(int group) {
  int result = 0;
  int otherGroup;
  for (int& bridge : data[group]) {
    otherGroup = findTheOtherEndGroup(group, bridge);
    if (otherGroup == 0) return bridge;
  }
  return result;
}
bool DFS(int group, int var) {
  visited[abs(group)] = true;
  res[abs(var)] = var > 0 ? 1 : 0;
  for (int& other : data[abs(group)]) {
    int newGroup = findTheOtherEndGroup(abs(group), other);
    if (newGroup == 0) {
      res[abs(other)] = other > 0 ? 1 : 0;
      continue;
    }
    int otherEnd =
        newGroup > 0 && other > 0 || newGroup < 0 && other < 0 ? 1 : -1;
    newGroup = abs(newGroup);
    if (!visited[newGroup]) {
      if (otherEnd == 1) {
        if (other != var) {
          res[abs(other)] = other > 0 ? 1 : 0;
          if (DFS(newGroup, otherEnd * other) == false) {
            return false;
          }
        } else {
          res[abs(other)] = other > 0 ? 1 : 0;
          if (DFS(newGroup, otherEnd * other) == false) {
            return false;
          }
        }
      } else {
        if (other != var) {
          res[abs(other)] = other > 0 ? 0 : 1;
          if (DFS(newGroup, otherEnd * other) == false) {
            return false;
          }
        } else {
          nNode[newGroup]--;
          if (nNode[newGroup] == 0) {
            return false;
          }
          if (nNode[newGroup] == 1 && curPos + 1 > newGroup) {
            groups.push_back(newGroup);
          }
        }
      }
    }
  }
  return true;
}
int main() {
  ios::sync_with_stdio(false);
  auto start = get_time::now();
  cin >> n >> m;
  data.push_back({});
  for (int i = 1; i <= n; i++) {
    int number, k;
    cin >> k;
    nNode[i] = k;
    if (k == 0) {
      cout << "NO";
      return 0;
    }
    data.push_back({});
    groups.push_back(i);
    if (n == 200000 && i == n / 2) {
      auto end = get_time::now();
      auto diff = end - start;
    }
    for (int j = 0; j < k; j++) {
      cin >> number;
      data[i].push_back(number);
      if (number < 0) {
        if (mapToGroup[-number].first == 0)
          mapToGroup[-number].first = -i;
        else
          mapToGroup[-number].second = -i;
      } else {
        if (mapToGroup[number].first == 0)
          mapToGroup[number].first = i;
        else
          mapToGroup[number].second = i;
      }
    }
  }
  if (n == 200000) {
    auto end = get_time::now();
    auto diff = end - start;
  }
  for (curPos = 0; curPos < groups.size(); curPos++) {
    int realGroup = groups[curPos];
    if (!visited[realGroup]) {
      int halfBridge;
      halfBridge = findHalfBridge(realGroup);
      if (halfBridge != 0) {
        if (!DFS(realGroup, halfBridge)) {
          if (n == 10 && m == 9) {
            auto end = get_time::now();
            auto diff = end - start;
          }
          cout << "NO";
          return 0;
        }
      } else if (nNode[realGroup] == 1) {
        int targetBridge = 0;
        for (auto& it : data[realGroup]) {
          if (res[abs(it)] == -1) {
            targetBridge = it;
            break;
          }
        }
        if (!DFS(realGroup, targetBridge)) {
          if (n == 10 && m == 9) {
            auto end = get_time::now();
            auto diff = end - start;
          }
          cout << "NO";
          return 0;
        }
      } else if (nNode[realGroup] == 0) {
        cout << "NO";
        if (n == 10 && m == 9) {
          auto end = get_time::now();
          auto diff = end - start;
        }
        return 0;
      }
    }
  }
  if (n == 199900 && m == 199899) {
    auto end = get_time::now();
    auto diff = end - start;
  }
  for (int i = 1; i <= n; i++) {
    if (!visited[i]) {
      int targetBridge = 0;
      for (auto& it : data[i]) {
        if (res[abs(it)] == -1) {
          targetBridge = it;
          break;
        }
      }
      if (!DFS(i, targetBridge)) {
        cout << "NO";
        return 0;
      }
    }
  }
  cout << "YES" << endl;
  for (int i = 1; i <= m; i++) {
    if (res[i] == -1) {
      cout << 1;
    } else {
      cout << res[i];
    }
  }
  return 0;
}
