#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;

// Geniosity pragmas
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")

// Macros
#define F first
#define S second
#define all(x) begin(x), end(x)
#define allr(x) rbegin(x), rend(x)

// Aliases
using ll = long long;
using ull = unsigned long long;
using ld = long double;

// Constants
constexpr ll INF = 2e18;
constexpr ld EPS = 1e-9;
constexpr int MOD = 1000000007;

// Temporary macro
#define int long long

// Ordered set
template <typename T>
using oset = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

// Custom hash map
struct custom_hash
{
	static uint64_t splitmix64(uint64_t x)
	{
		// http://xorshift.di.unimi.it/splitmix64.c
		x += 0x9e3779b97f4a7c15;
		x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
		x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
		return x ^ (x >> 31);
	}

	size_t operator()(uint64_t x) const
	{
		static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
		return splitmix64(x + FIXED_RANDOM);
	}
};
// Use int type for keys
template <typename T1, typename T2>
using safe_map = unordered_map<T1, T2, custom_hash>;
template <typename T>
using GPTable = gp_hash_table<int, T>;

// Operator overloads
// cin >> pair<T1, T2>
template<typename T1, typename T2>
istream& operator>>(istream &istream, pair<T1, T2> &p)
{
    istream >> p.first >> p.second;
    return istream;
}
// cin >> vector<T>
template<typename T>
istream& operator>>(istream &istream, vector<T> &v)
{
    for (auto &it : v) cin >> it;
    return istream;
}
// cout << pair<T1, T2>
template<typename T1, typename T2>
ostream& operator<<(ostream &ostream, const pair<T1, T2> &p)
{
    ostream << p.first << " " << p.second;
    return ostream;
}
// cout << vector<T>
template<typename T>
ostream& operator<<(ostream &ostream, const vector<T> &c)
{
    for (auto &it : c) cout << it << " ";
    return ostream;
}

// Utility functions
template <typename T>
T MIN(T first) { return first; }
template <typename T, typename... Args>
T MIN(T first, Args... args) { return min(first, MIN(args...)); }

template <typename T>
T MAX(T first) { return first; }
template <typename T, typename... Args>
T MAX(T first, Args... args) { return max(first, MAX(args...)); }

template <typename T>
void print(T &&t) 
{ 
    cout << t << "\n"; 
}
template <typename T, typename... Args>
void print(T &&t, Args &&... args)
{
	cout << t << " ";
	print(forward<Args>(args)...);
}

template <typename T>
int32_t size_i(T &container) { return static_cast<int32_t>(container.size()); }

// Mathematical functions
int GCD(int a, int b)
{
	if (!b) return a;
	return GCD(b, a % b);
}
int LCM(int a, int b)
{
	return (a * b) / GCD(a, b);
}
int modpow(int x, int n, int m = MOD)
{
	if (n == 0) return 1 % m;
	long long u = modpow(x, n / 2, m);
	u = (u * u) % m;
	if (n % 2 == 1) u = (u * x) % m;
	return u;
}
// @param m should be prime
int modinv(int x, int m = MOD)
{
	return modpow(x, m - 2, m);
}

// Flags to use: -std=c++17 -O2 -Wshadow -DLOCAL_PROJECT -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -fsanitize=address -fsanitize=undefined
////////////////////////////////// START CODE HERE //////////////////////////////////

void preSolve() {}

int mul(int x, int y)
{
	return (x * y) % MOD;
}

struct In
{
	int x, y, idx;
	In() = default;
	In(int x, int y, int idx)
		: x(x), y(y), idx(idx) {}
};

void solve(int /* tc */)
{
	int n, m;
	cin >> n >> m;
	set<pair<int, int>> units;
	vector<int> ans;
	vector<In> a;

	for (int i = 0; i < n; i++)
	{
		int k, x, y;
		cin >> k >> x;
		if (k > 1) cin >> y;
		else y = 0;
		a.emplace_back(x, y, i);
	}

	// sort(all(a), [&](In& x, In& y)
	// {
	// 	return make_pair(x.x, x.y) < make_pair(y.x, y.y);
	// });

	for (auto &[x, y, idx] : a)
	{
		if (y == 0)
		{
			units.insert({x, y});
			ans.push_back(idx + 1);
		}else
		{
			if (units.count({x, 0}) && units.count({y, 0}))
			{
				// do nothing
			}else
			{
				units.insert({x, y});
				ans.push_back(idx + 1);
			}
		}
	}
	sort(all(ans));
	cout << modpow(2, ans.size()) << " " << ans.size() << "\n";
	cout << ans << "\n";
}	

int32_t main()
{
    // #ifdef LOCAL_PROJECT
	// 	freopen("input.txt", "r", stdin);
	// 	freopen("output.txt", "w", stdout);
	// #endif

    ios_base::sync_with_stdio(false);
	cin.tie(0);
    cout << setprecision(12) << fixed;

    preSolve();

    int tests = 1;
    // cin >> tests;
    for (int t = 1; t <= tests; t++)
        solve(t);
    
    return 0;
}