#include <bits/stdc++.h>
using namespace std;
string to_string(char c) { return "'" + string(1, c) + "'"; }
string to_string(string s) { return '"' + s + '"'; }
string to_string(bool f) {
  if (f)
    return "True";
  else
    return "False";
}
string to_string(const char *s) { return to_string((string)s); }
template <typename A>
string to_string(A);
template <typename A, typename B>
string to_string(pair<A, B> p) {
  return "(" + to_string(p.first) + ": " + to_string(p.second) + ")";
}
template <typename A>
string to_string(A v) {
  bool f = false;
  string r = "{";
  for (auto x : v) {
    if (f) r += ", ";
    r += to_string(x);
    f = true;
  }
  return r += "}";
}
template <typename A>
string to_string(vector<vector<A>> v) {
  string r;
  for (auto x : v) r += "\n" + to_string(x);
  return r;
}
int Nerr;
template <typename A>
string to_string(A *p) {
  return to_string(vector<A>(p, p + Nerr));
}
void err(istream_iterator<string>) { cerr << '\n'; }
template <typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
  cerr << *it << " = " << to_string(a) << "; ";
  err(++it, args...);
}
template <typename T>
void kek(T ans) {
  cout << ans << '\n';
  exit(0);
}
int power(int x, unsigned int y, unsigned int m) {
  if (y == 0) return 1;
  int p = power(x, y / 2, m) % m;
  p = (p * 1ll * p) % m;
  return (y % 2 == 0) ? p : (x * 1ll * p) % m;
}
vector<vector<int>> v;
vector<int> nex(500005, 0);
int parent[500005];
void make_set(int v) { parent[v] = v; }
int find_set(int v) {
  if (v == parent[v]) return v;
  return parent[v] = find_set(parent[v]);
}
void union_sets(int a, int b) {
  a = find_set(a);
  b = find_set(b);
  if (a != b) parent[a] = b;
}
vector<int> ans;
void add1(int x, int i) {
  if (!nex[x]) {
    ans.push_back(i + 1);
    nex[x] = x;
    make_set(x);
  } else {
    int cur = find_set(x);
    if (nex[cur] == cur) return;
    ans.push_back(i + 1);
    nex[cur] = cur;
    union_sets(x, cur);
  }
}
signed main() {
  ios_base::sync_with_stdio(0);
  int TESTS = 1;
  while (TESTS--) {
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
      int k;
      cin >> k;
      vector<int> t;
      for (int j = 0; j < k; j++) {
        int r;
        cin >> r;
        t.push_back(r);
      }
      v.push_back(t);
    }
    for (int i = 0; i < n; i++) {
      if ((int)v[i].size() == 1) {
        add1(v[i][0], i);
      } else {
        int cur1 = v[i][0], cur2 = v[i][1];
        if (nex[cur1]) cur1 = find_set(cur1);
        if (nex[cur2]) cur2 = find_set(cur2);
        if (nex[cur1] == cur1) add1(cur2, i);
        if (nex[cur2] == cur2) add1(cur1, i);
        if (cur1 > cur2) swap(cur1, cur2);
        nex[cur1] = cur2;
        make_set(cur1);
        make_set(cur2);
        ans.push_back(i + 1);
        union_sets(cur1, cur2);
      }
    }
    int size = 0;
    for (int i = 1; i < m + 1; i++)
      if (nex[i]) size++;
    cout << power(2, size, 1000000007) << " " << (int)ans.size() << '\n';
    for (auto j : ans) cout << j << " ";
    cout << '\n';
  }
}
