#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using cd = complex<ld>;

template<int MOD>
struct modInt {
  int x;

  void normalize() {
    if (x < 0) x += MOD;
    else if (x >= MOD) x -= MOD;
  }

  modInt() = default;

  modInt(int x) : x(x) {
    normalize();
  }

  modInt(ll x) : x(x % MOD) {
    normalize();
  }

  friend modInt operator+(const modInt &a, const modInt &b) {
    return modInt(a.x + b.x);
  }

  friend modInt operator-(const modInt &a, const modInt &b) {
    return modInt(a.x - b.x);
  }

  friend modInt operator*(const modInt &a, const modInt &b) {
    return modInt((ll) a.x * b.x);
  }

  friend modInt operator/(modInt a, modInt b) {
    int p = MOD - 2;
    while (p > 0) {
      if (p & 1) {
        a = a * b;
      }
      b = b * b;
      p >>= 1;
    }
    return a;
  }

  modInt &operator+=(const modInt &b) {
    return *this = *this + b;
  }

  modInt &operator-=(const modInt &b) {
    return *this = *this - b;
  }

  modInt &operator*=(const modInt &b) {
    return *this = *this * b;
  }

  modInt &operator/=(const modInt &b) {
    return *this = *this / b;
  }
};

template<int MOD>
ostream &operator<<(ostream &out, modInt<MOD> const &x) {
  out << x.x;
  return out;
}

using mint = modInt<1'000'000'007>;

const int N = (int) 5e5 + 100;

vector<int> a[N];
bool one[N];
vector<int> res;

int p[N];

int findSet(int v) {
  return p[v] == v ? v : p[v] = findSet(p[v]);
}

int merge(int u, int v) {
  u = findSet(u);
  v = findSet(v);
  if (u == v) {
    return 0;
  }
  p[v] = u;
  return 1;
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);

  int n, m;
  cin >> n >> m;
  for (int i = 0; i < n; i++) {
    int k;
    cin >> k;
    for (int j = 0; j < k; j++) {
      int x;
      cin >> x;
      --x;
      a[i].push_back(x);
    }
    sort(a[i].begin(), a[i].end());
  }

  iota(p, p + m, 0);

  for (int i = 0; i < n; i++) {
    int k = (int) a[i].size();
    if (k == 1) {
      if (one[a[i][0]]) {
        continue;
      }
      res.push_back(i + 1);
      one[a[i][0]] = true;
    } else {
      int x1 = a[i][0], x2 = a[i][1];
      if (one[x1]) {
        x1 = -1;
      }
      if (one[x2]) {
        x2 = -1;
      }

      if (x1 == -1 && x2 == -1) {
        continue;
      } else if (x1 != -1 && x2 == -1) {
        one[x1] = true;
        res.push_back(i + 1);
      } else if (x2 != -1 && x1 == -1) {
        one[x2] = true;
        res.push_back(i + 1);
      } else {
        if (merge(x1, x2)) {
          res.push_back(i + 1);
        }
      }
    }
  }

  mint comb = 1;
  for (int i = 0; i < (int) res.size(); i++) {
    comb *= 2;
  }
  cout << comb << " " << res.size() << "\n";
  sort(res.begin(), res.end());
  for (int id : res) {
    cout << id << " ";
  }
  return 0;
}
