二分图建图+tarjan强联通
#include<bits/stdc++.h>
#define Mem(a,b) memset(a,b,sizeof(a))
#define N 10000
using namespace std;
vector<int> G[10000];
set<int> ans[4000];
struct edge {
int v,next;
edge() {};
edge(int _v,int _next) {
v=_v;
next=_next;
}
} e[10000000];
int head[N],cnt,dfn[N],low[N],pre[N],aft[N],n,m,top,scc,belong[N],p,st[N];
bool used[N],instack[N];
void add(int u,int v) {
e[cnt]=edge(v,head[u]);
head[u]=cnt++;
}
void init() {
for(int i=1; i<=n+m; i++){
G[i].clear();
ans[i].clear();
}
Mem(head,-1);
cnt=0;
Mem(dfn,0);
Mem(low,0);
p=0;
Mem(instack,0);
top=0;
scc=0;
Mem(belong,0);
}
bool dfs(int u) {
for(int i=0; i<G[u].size(); i++) {
int v=G[u][i];
if(!used[v]) {
used[v]=1;
if(!pre[v]||dfs(pre[v])) {
pre[v]=u;
aft[u]=v;
return true;
}
}
}
return false;
}
int work(int n) {
int res=0;
Mem(pre,0);
Mem(aft,0);
for(int i=1; i<=n; i++) {
Mem(used,0);
if(dfs(i)) res++;
}
return res;
}
void tarjan(int u) {
dfn[u] = low[u] = ++ p;
st[top ++] = u;
instack[u] = 1;
for (int i = head[u]; i + 1; i = e[i].next) {
int v = e[i].v;
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u],low[v]);
} else if (instack[v])
low[u] = min(low[u],dfn[v]);
}
int v;
if (low[u] == dfn[u]) {
++ scc;
do {
v = st[-- top];
instack[v] = 0;
belong[v] = scc;
} while (u != v);
}
}
int main() {
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int cas;
for(scanf("%d",&cas); cas--;) {
init();
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) {
int s;
scanf("%d",&s);
while(s--) {
int v;
scanf("%d",&v);
G[i].push_back(v);
}
}
int ansnum=work(n);
printf("%d\n",ansnum);
for(int i=n+1; i<=m+n-ansnum; i++) {
for(int j=1; j<=m+n-ansnum; j++) G[i].push_back(j);
}
for(int i=1; i<=m+n-ansnum; i++) {
for(int j=m+1; j<=m+n-ansnum; j++) G[i].push_back(j);
}
work(n+m-ansnum);
for(int i=1; i<=n+m-ansnum; i++) {
for(int j=0; j<G[i].size(); j++) {
int v=G[i][j];
if(v!=aft[i]) {
add(aft[i],v);
}
}
}
for(int i=1;i<=n+m-ansnum;i++){
if(!dfn[i]) tarjan(i);
}
for(int i=1;i<=n;i++){
int aim=aft[i];
for(int j=0;j<G[i].size();j++){
int v=G[i][j];
if(v<=m&&belong[v]==belong[aim]) ans[i].insert(v);
}
}
set<int>::iterator it;
for(int i=1;i<=n;i++){
cout<<ans[i].size();
for(it=ans[i].begin();it!=ans[i].end();it++) printf(" %d",*it);
printf("\n");
}
}
}