/*
先定一个结尾:只出现一次的都可以当成结尾,然后把结尾所在的集合影响删掉,继续往前找
找完一整个序列后还要再和给定的序列比较一下看是不是满足要求
注意前两个数要特判,第一个数肯定比第二个数出现次数少
*/
#include<bits/stdc++.h>
using namespace std;
#define N 505
int vis[N],n,cnt[N];
set<int>s[N],ss[N];
vector<int>ans;
struct Node{
int c,f,id;//出现次数,在上一个数组中是否出现过
}p[N];
int cmp(Node a,Node b){
if(a.c==b.c)return a.f>b.f;
return a.c<b.c;
}
int pos;
int solve(int end){
pos=0;
ans.clear();
memset(p,0,sizeof p);
memset(vis,0,sizeof vis);
int num=end,now;
for(int i=1;i<=n;i++)
p[i].c=cnt[i],p[i].f=0,p[i].id=i;
ans.push_back(num);p[num].c=100000;
for(int i=2;i<=n;i++)
if(s[i].find(num)!=s[i].end())
now=i,vis[i]=1;
ss[++pos]=s[now];
for(auto x:s[now])p[x].c--,p[x].f=1;
for(int i=1;i<=n-2;i++){
sort(p+1,p+1+n,cmp); //按出现次数排序
int tmp[N];
for(int j=1;j<=n;j++)tmp[p[j].id]=j;
if(p[1].c!=1)return 0;
if(p[1].f==0)return 0;
num=p[1].id;
ans.push_back(num);p[tmp[num]].c=100000;
now=-1;
for(int j=2;j<=n;j++)
if(!vis[j] && s[j].find(num)!=s[j].end())
now=j,vis[j]=1;
if(now==-1)return 0;
for(int j=1;j<=n;j++)p[j].f=0;
for(auto x:s[now])p[tmp[x]].c--,p[tmp[x]].f=1;
}
for(int i=1;i<=n;i++)
if(p[i].c==0)ans.push_back(p[i].id);
if(ans.size()!=n)return 0;
int i=0,j=ans.size()-1;
while(i<j)
swap(ans[i],ans[j]),i++,j--;
if(cnt[ans[0]]>cnt[ans[1]])swap(ans[0],ans[1]);
if(ans.size()==n)return 1;
for(int i=2;i<=n;i++){
set<int>t;
for(int j=i-ss[i].size()+1;j<=i-1;j++)
t.insert(ans[j]);
if(t!=ss[i])return 0;
}
return 0;
}
int main(){
int t;cin>>t;
while(t--){
memset(cnt,0,sizeof cnt);
cin>>n;
for(int i=1;i<=n;i++)s[i].clear();
for(int i=2;i<=n;i++){
int k,x;scanf("%d",&k);
while(k--){
scanf("%d",&x);
s[i].insert(x);
cnt[x]++;
}
}
for(int i=1;i<=n;i++)if(cnt[i]==1){
int res=solve(i);
if(res)break;
}
for(int i=0;i<ans.size();i++)
cout<<ans[i]<<" ";
puts("");
}
}