#include <bits/stdc++.h>
#include <unordered_map>
#include <chrono>
#include <random>

#define mp make_pair
#define pb push_back
#define ll long long
#define ll_MAX 1e18

ll MOD = 1e9 + 7;
ll bigMOD = 998244353;
using namespace std;

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        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);
    }
};
long long gcd(long long int a, long long int b)
{
    if (b == 0)
        return a;
    return gcd(b, a % b);
}

/* Iterative Function to calculate (x^y)%p
in O(log y) */
unsigned long long power(unsigned long long x,
    int y, int p)
{
    unsigned long long res = 1; // Initialize result

    x = x % p; // Update x if it is more than or
    // equal to p

    while (y > 0)
    {

        // If y is odd, multiply x with result
        if (y & 1)
            res = (res * x) % p;

        // y must be even now
        y = y >> 1; // y = y/2
        x = (x * x) % p;
    }
    return res;
}

// Returns n^(-1) mod p
unsigned long long modInverse(unsigned long long n,
    int p)
{
    return power(n, p - 2, p);
}


int main() {

    ios::sync_with_stdio(false);
    cin.tie(NULL);

    int aa = 0; cin >> aa;

    for (int qq = 0; qq < aa; qq++) {
        int n; cin >> n;
        
        vector<vector<int>> nums;

        //pos[i][j] means number of j in position i
        vector<vector<vector<int>>> pos;

        vector<vector<int>> posC;

        pos.resize(n);
        posC.resize(n);

        for (int i = 0; i < n; i++) {
            pos[i].resize(n);
            posC[i].resize(n);
        }

        for (int i = 0; i < 2*n; i++) {
            nums.push_back(vector<int>());
            for (int j = 0; j < n; j++) {
                int k; cin >> k; k--; nums[i].push_back(k);
                pos[j][k].push_back(i); posC[j][k]++;
            }
        }

        int counter = 0;
        int x = n;
        queue<int> list;

        vector<int> used;
        used.resize(2 * n);

        bool yes = false;

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (pos[i][j].size()==1&&!used[pos[i][j][0]]) {
                    list.push(pos[i][j][0]);
                    yes = true;
                    break;
                }
            }
            if (yes) {
                break;
            }
        }

        if (list.size()==0) {
            list.push(0);
            counter++;
        }

        vector<int> ans;

        while (x>0) {

            while (list.size()!=0) {
                int k = list.front();
                list.pop();
                x--;

                ans.push_back(k);

                used[k] = true;
                for (int i = 0; i < n; i++) {
                    int j = nums[k][i];
                    vector<int> temp = pos[i][j];

                    for (int d = 0; d < temp.size(); d++) {
                        if (!used[temp[d]]) {
                            used[temp[d]] = true;
                            for (int e = 0; e < n; e++) {
                                posC[e][nums[temp[d]][e]]--;
                            }
                        }
                    }

                    posC[i][j]=0;
                }

                bool found = false;

                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < n; j++) {
                        if (posC[i][j] == 1) {
                            for (int q = 0; q < pos[i][j].size(); q++) {
                                if (!used[pos[i][j][q]]) {
                                    list.push(pos[i][j][q]);
                                    found = true;
                                    break;
                                }
                            }
                        }

                        if (found) {
                            break;
                        }
                    }
                    if (found) {
                        break;
                    }
                }
            }
            counter++;

            bool found = false;

            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    if (posC[i][j] > 0) {
                        for (int q = 0; q < pos[i][j].size(); q++) {
                            if (!used[pos[i][j][q]]) {
                                list.push(pos[i][j][q]);
                                found = true;
                                break;
                            }
                        }
                    }

                    if (found) {
                        break;
                    }
                }
                if (found) {
                    break;
                }
            }
        }

        cout << power(2, counter-1, bigMOD) << endl;
        for (int i = 0; i < n; i++) {
            cout << ans[i]+1 << " ";
        }
        cout << endl;
        
    }





}