(二分图染色+01背包),若两人中至少有其中一人不认识对方则建立一条边。
#include"cstdio"
#include"iostream"
#include"algorithm"
#include"cstring"
#include"vector"
using namespace std;
const int MX = 1e5+7;
const int maxn = 505;
struct edge{
int v,nxt;
edge(){}
edge(int v ,int nxt):v(v), nxt(nxt){}
}e[MX];
int n;
int cnt,tail,head[maxn],col[maxn],sz[maxn],dp[maxn][maxn];
vector <int> d[maxn];
bool flag;
bool mp[maxn][maxn];
void init()
{
cnt = 1;
flag = 0;
tail = -1;
memset(col,-1,sizeof(col));
memset(head,-1,sizeof(head));
memset(mp,0,sizeof(mp));
for(int i = 0; i <= 2*n+1; i++) d[i].clear();
}
void Add(int u, int v){
e[++tail] = edge(v,head[u]);
head[u] = tail;
}
void dfs(int u, int c)
{
if(flag) return;
col[u] = c;
d[cnt+c].push_back(u);
for(int i = head[u]; ~i; i = e[i].nxt){
int v = e[i].v;
if(col[v] != -1 && col[v]!=c^1){
flag = 1;
return;
}
if(col[v] == -1)
dfs(v,c^1);
}
}
void Print()
{
int now = 0;
for(int i = 0; i <=n ; i++){
if(dp[cnt][n+i] == 1){
now = n+i;
break;
}
else if(dp[cnt][n-i] == 1){
now = n-i;
break;
}
}
vector <int> q1,q2;
for(int i = cnt; i > 0; i--){
if(dp[i-1][now-sz[i]]){
for(int j = 0; j < d[2*i-1].size(); j++) q1.push_back(d[2*i-1][j]);
for(int j = 0; j < d[2*i].size(); j++) q2.push_back(d[2*i][j]);
now -= sz[i];
}
else{
for(int j = 0; j < d[2*i-1].size(); j++) q2.push_back(d[2*i-1][j]);
for(int j = 0; j < d[2*i].size(); j++) q1.push_back(d[2*i][j]);
now += sz[i];
}
}
printf("%d",q1.size());
for(int i = 0; i < q1.size(); i++) printf(" %d",q1[i]);
puts("");
printf("%d",q2.size());
for(int i = 0; i < q2.size(); i++) printf(" %d",q2[i]);
puts("");
}
void DP()
{
cnt /= 2;
for(int i = 1; i <= cnt; i++){
sz[i] = d[2*i-1].size() - d[2*i].size();
}
memset(dp,0,sizeof(dp));
dp[0][n] = 1;
int m = 2*n;
for(int i = 1; i <= cnt; i++){
for(int j = m; j >= 0; j--){
if(dp[i-1][j]){
dp[i][j+sz[i]] = 1;
dp[i][j-sz[i]] = 1;
}
}
}
Print();
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
init();
for(int i = 1; i<= n; i++){
int x;
scanf("%d",&x);
while(x){
mp[i][x] = 1;
scanf("%d",&x);
}
}
for(int i = 1; i<= n; i++){
for(int j = 1; j <= n; j++)
if(i != j){
if(mp[i][j] && mp[j][i]) continue;
Add(i,j);
}
}
for(int i = 1; i <= n; i++){
if(col[i] == -1){
dfs(i,0);
cnt += 2;
if(flag){
puts("No solution\n");
break;
}
}
}
if(flag) continue;
DP();
if(T) puts("");
}
return 0;
}