#include <bits/stdc++.h>
using namespace std;
template <typename T>
ostream& operator<<(ostream& os, vector<T> v) {
  for (int i = 0; i < (v.size()); ++i) os << v[i] << " ";
  os << endl;
  return os;
}
template <typename T1, typename T2>
ostream& operator<<(ostream& os, pair<T1, T2> p) {
  os << "(" << p.first << ", " << p.second << ")";
  return os;
}
vector<int> v[300030];
vector<int> ke[300030];
vector<int> p;
int n, m;
bool used[300030];
int color[300030];
void dfs(int i, int first) {
  p.push_back(i);
  for (int k = 0; k < (ke[i].size()); ++k) {
    int j = ke[i][k];
    if (j != first) {
      dfs(j, i);
    }
  }
}
int main() {
  cout.sync_with_stdio(false);
  cin >> n >> m;
  for (int i = (1); i <= (n); ++i) {
    int s;
    cin >> s;
    for (int j = 0; j < (s); ++j) {
      int x;
      cin >> x;
      v[i].push_back(x);
    }
  }
  for (int i = 0; i < (n - 1); ++i) {
    int u, v;
    cin >> u >> v;
    ke[u].push_back(v);
    ke[v].push_back(u);
  }
  dfs(1, -1);
  for (int kk = 0; kk < (p.size()); ++kk) {
    int i = p[kk];
    for (int k2 = 0; k2 < (v[i].size()); ++k2) {
      int u = v[i][k2];
      if (color[u] != 0) used[color[u]] = true;
    }
    int firstToConsider = 1;
    for (int k2 = 0; k2 < (v[i].size()); ++k2) {
      int u = v[i][k2];
      if (color[u] == 0) {
        while (used[firstToConsider]) ++firstToConsider;
        color[u] = firstToConsider;
        used[firstToConsider] = true;
      }
    }
    for (int k2 = 0; k2 < (v[i].size()); ++k2) {
      int u = v[i][k2];
      used[color[u]] = false;
    }
  }
  for (int i = (1); i <= (m); ++i)
    if (color[i] == 0) color[i] = 1;
  int max = *max_element(color + 1, color + 1 + m);
  cout << max << endl;
  for (int i = (1); i <= (m); ++i) cout << color[i] << " ";
  cout << endl;
  return 0;
}
