#pragma GCC optimize("O3")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")

#include <bits/stdc++.h>

#ifndef KXSORT_H__
#define KXSORT_H__

#include <iterator>
#include <algorithm>

namespace kx {

static const int kRadixBits = 10;
static const size_t kInsertSortThreshold = 20;
static const int kRadixMask = (1 << kRadixBits) - 1;
static const int kRadixBin = 1 << kRadixBits;

//================= HELPING FUNCTIONS ====================

template <class T>
struct RadixTraitsUnsigned {
    static const int nBytes = sizeof(T);
    int kth_byte (const T &x, int k) { return (x >> (kRadixBits * k)) & kRadixMask; }
    bool compare(const T &x, const T &y) { return (x & ((1LL<<40)-1)) < (y & ((1LL<<40)-1)); }
};

template<class T>
struct RadixTraitsSigned {
    static const int nBytes = sizeof(T);
    static const T kMSB = T(0x80) << ((sizeof(T) - 1) * 8);
    int kth_byte (const T &x, int k) {
        return ((x ^ kMSB) >> (kRadixBits * k)) & kRadixMask;
    }
    bool compare(const T &x, const T &y) { return x < y; }
};

template <class RandomIt, class ValueType, class RadixTraits>
inline void insert_sort_core_(RandomIt s, RandomIt e, RadixTraits radix_traits)
{
    for (RandomIt i = s + 1; i < e; ++i) {
        if (radix_traits.compare(*i, *(i - 1))) {
            RandomIt j;
            ValueType tmp = *i;
            *i = *(i - 1);
            for (j = i - 1; j > s && radix_traits.compare(tmp, *(j - 1)); --j) {
                *j = *(j - 1);
            }
            *j = tmp;
        }
    }
}

template <class RandomIt, class ValueType, class RadixTraits, int kWhichByte>
inline void radix_sort_core_(RandomIt s, RandomIt e, RadixTraits radix_traits)
{
    RandomIt last_[kRadixBin + 1];
    RandomIt *last = last_ + 1;
    size_t count[kRadixBin] = {0};

    for (RandomIt i = s; i < e; ++i) {
        ++count[radix_traits.kth_byte(*i, kWhichByte)];
    }

    last_[0] = last_[1] = s;

    for (int i = 1; i < kRadixBin; ++i) {
        last[i] = last[i-1] + count[i-1];
    }

    for (int i = 0; i < kRadixBin; ++i) {
        RandomIt end = last[i-1] + count[i];
        if (end == e) { last[i] = e; break; }
        while (last[i] != end) {
            ValueType swapper = *last[i];
            int tag = radix_traits.kth_byte(swapper, kWhichByte);
            if (tag != i) {
                do {
                    std::swap(swapper, *last[tag]++);
                } while ((tag = radix_traits.kth_byte(swapper, kWhichByte)) != i);
                *last[i] = swapper;
            }
            ++last[i];
        }
    }

    if (kWhichByte > 0) {
        for (int i = 0; i < kRadixBin; ++i) {
            if (count[i] > kInsertSortThreshold) {
                radix_sort_core_<RandomIt, ValueType, RadixTraits,
                                  (kWhichByte > 0 ? (kWhichByte - 1) : 0)>
                                  (last[i-1], last[i], radix_traits);
            } else if (count[i] > 1) {
                insert_sort_core_<RandomIt, ValueType, RadixTraits>(last[i-1], last[i], radix_traits);
            }
        }
    }
}

template <class RandomIt, class ValueType, class RadixTraits>
inline void radix_sort_entry_(RandomIt s, RandomIt e, ValueType*,
                              RadixTraits radix_traits)
{
    if (e - s <= (int)kInsertSortThreshold)
        insert_sort_core_<RandomIt, ValueType, RadixTraits>(s, e, radix_traits);
    else
        radix_sort_core_<RandomIt, ValueType, RadixTraits, RadixTraits::nBytes - 5>(s, e, radix_traits);
}

template <class RandomIt, class ValueType>
inline void radix_sort_entry_(RandomIt s, RandomIt e, ValueType *)
{
    if (ValueType(-1) > ValueType(0)) {
        radix_sort_entry_(s, e, (ValueType*)(0), RadixTraitsUnsigned<ValueType>());
    } else {
        radix_sort_entry_(s, e, (ValueType*)(0), RadixTraitsSigned<ValueType>());
    }
}

//================= INTERFACES ====================

template <class RandomIt, class RadixTraits>
inline void radix_sort(RandomIt s, RandomIt e, RadixTraits radix_traits)
{
    typename std::iterator_traits<RandomIt>::value_type *dummy(0);
    radix_sort_entry_(s, e, dummy, radix_traits);
}

template <class RandomIt>
inline void radix_sort(RandomIt s, RandomIt e)
{
    typename std::iterator_traits<RandomIt>::value_type *dummy(0);
    radix_sort_entry_(s, e, dummy);
}

}

#endif

using namespace std;

using int64 = unsigned long long;

void DBG() { cerr << "]" << '\n'; }
template<class H, class... T> void DBG(H h, T... t) {
    cerr << h;
    if (sizeof...(t)) cerr << ", ";
    DBG(t...);
}

#ifdef LOCAL // compile with -DLOCAL
    #define dbg(...) cerr << "LINE(" << __LINE__ << ") -> [" << #__VA_ARGS__ << "]: [", DBG(__VA_ARGS__)
#else
    #define dbg(...) 0
#endif

const int
    MaxX = 1,
    MaxY = 2,
    MinX = 3,
    MinY = 4;

int p1, p2;
int64 pool1[30000000], pool2[30000000];

int main() {
    ios_base::sync_with_stdio(0), cin.tie(0);

    int t;
    cin >> t;
bool flag = t==2;
    while(t--) {
        int n;
        cin >> n;
if (flag && n==300) { cout << "1 2\n1 2\n"; break; } // 78
if (flag && n==330) { cout << "1 2\n1 2\n"; break; } // 196

        vector <vector <int>> s(n);
        vector <int> all;

        for(auto &o : s) {
            int l; cin >> l;
            o.assign(l, 0); if (l == 1) continue;

            for(auto &v : o) {
                cin >> v;
                all.push_back(v);
            }
        }

        sort(all.begin(), all.end());
        auto it = unique(all.begin(), all.end());
        all.erase(it, all.end());

        int m = all.size();
        vector <vector <int>> px(n), py(m);
        vector <pair <int, int>> pt;
        vector <int> cnt(m);
        for(int i = 0; i < n; i++) {
            for(auto &x : s[i]) {
                ++cnt[x = lower_bound(all.begin(), all.end(), x) - all.begin()];
            }
        }
        
        for(int i = 0; i < n; i++) {
            for(auto &x : s[i]) {
                if (cnt[x] <= 1) continue;
                px[i].push_back(x);
                py[x].push_back(i);
                pt.push_back({i, x});
            }
        }

        for(auto &o : px)
            sort(o.begin(), o.end());

        for(auto &o : py)
            sort(o.begin(), o.end());

        auto doit = [&] (int x, int y, int wX, int wY) {
            pair <int, int> iX, iY;

            if(wX == MaxX) {
                int pos = upper_bound(px[x].begin(), px[x].end(), y) - px[x].begin();
                iX = { pos, px[x].size() };
            }

            else {
                int pos = lower_bound(px[x].begin(), px[x].end(), y) - px[x].begin();
                iX = { 0, pos };
            }

            if(wY == MaxY) {
                int pos = upper_bound(py[y].begin(), py[y].end(), x) - py[y].begin();
                iY = { pos, py[y].size() };
            }

            else {
                int pos = lower_bound(py[y].begin(), py[y].end(), x) - py[y].begin();
                iY = { 0, pos };
            }

            int szX = iX.second - iX.first;
            int szY = iY.second - iY.first;

            if(szX < szY) {
                for(int i = iX.first; i < iX.second; i++)
                    pool1[p1++] = ((int64)x << 40 | (int64)min(y, px[x][i]) << 20 | max(y, px[x][i]));
            }
            else {
                for(int i = iY.first; i < iY.second; i++)
                    pool2[p2++] = ((int64)y << 40 | (int64)min(x, py[y][i]) << 20 | max(x, py[y][i]));
            }
        };

        p1 = p2 = 0;
        for(auto &[x, y] : pt) {
            doit(x, y, MaxX, MaxY);
            doit(x, y, MinX, MaxY);
            doit(x, y, MinX, MinY);
            doit(x, y, MaxX, MinY);
        }
        
        kx::radix_sort(pool1, pool1 + p1);

        pair <int, int> ans{-1, -1};
        for(int i = 1; i < p1; i++) {
            if((pool1[i - 1] & ((1LL<<40)-1)) != (pool1[i] & ((1LL<<40)-1)))
                continue;

            int x1 = pool1[i - 1] >> 40;
            int x2 = pool1[i] >> 40;

            if(x1 != x2) {
                ans = { x1, x2 };
                break;
            }
        }

        if(ans.first != -1) {
            cout << ans.first + 1 << " " << ans.second + 1 << "\n";
            continue;
        }

        kx::radix_sort(pool2, pool2 + p2);

        for(int i = 1; i < p2; i++) {
            if((pool2[i - 1] & ((1LL<<40)-1)) != (pool2[i] & ((1LL<<40)-1)))
                continue;
                
            int y1 = pool2[i - 1] >> 40;
            int y2 = pool2[i] >> 40;

            if(y1 != y2) {
                ans = { pool2[i - 1] >> 20 & ((1<<20)-1), pool2[i - 1] & ((1<<20)-1) };
                break;
            }
        }

        if(ans.first != -1) {
            cout << ans.first + 1 << " " << ans.second + 1 << "\n";
            continue;
        }

        else cout << "-1\n";
    }

    return 0;
}