这个题最开始打算是暴力的,结果发现不行。后来想DP的(看了白书上面的讲解),把不相互认识的人另外建图,然后求连通分量,转成01背包问题。输出的时候有点恶心,需要反着推回去
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
const int inf=1<<29;
const int maxn=110;
const int maxm=maxn*2;
int n,s[maxn][maxn],color[maxn],cnt[maxn][2],grp[maxn],ind;
vector<int> g[maxn],ans[2];
bool dp[maxn][maxn*2];
void Init()
{
memset(s,0,sizeof(s));
memset(color,-1,sizeof(color));
memset(cnt,0,sizeof(cnt));
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
g[i].clear();
ans[0].clear();ans[1].clear();
}
bool DFS(int u)
{
for(int i=0;i<g[u].size();i++)
{
if(color[g[u][i]]==-1)
{
grp[g[u][i]]=ind;
color[g[u][i]]=1-color[u];
cnt[ind][1-color[u]]++;
if(!DFS(g[u][i]))
return false;
}
else if(color[g[u][i]]==color[u])
return false;
}
return true;
}
void solve()
{
dp[0][100]=1;
for(int i=1;i<=ind;i++)
for(int j=0;j<maxm;j++)
if(dp[i-1][j])
{
dp[i][j+cnt[i][0]-cnt[i][1]]=1;
dp[i][j+cnt[i][1]-cnt[i][0]]=1;
}
int l=inf,r=inf;
for(int i=100;i<maxn;i++)
if(dp[ind][i])
{
r=i;
break;
}
for(int i=100;i>=0;i--)
if(dp[ind][i])
{
l=i;
break;
}
int now=0,snow=ind-1;
if(abs(l-100)<=abs(r-100))
now=l;
else
now=r;
while(snow>=0)
{
for(int i=0;i<maxm;i++)
if(dp[snow][i])
{
if(i+cnt[snow+1][0]-cnt[snow+1][1]==now)
{
for(int j=1;j<=n;j++)
if(grp[j]==snow+1)
{
if(color[j]==0)
ans[0].push_back(j);
else
ans[1].push_back(j);
}
now=i;
break;
}
if(i+cnt[snow+1][1]-cnt[snow+1][0]==now)
{
for(int j=1;j<=n;j++)
if(grp[j]==snow+1)
{
if(color[j]==0)
ans[1].push_back(j);
else
ans[0].push_back(j);
}
now=i;
break;
}
}
snow--;
}
for(int i=0;i<2;i++)
{
printf("%d",ans[i].size());
for(int j=0;j<ans[i].size();j++)
printf(" %d",ans[i][j]);
printf("\n");
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
Init();
for(int i=1;i<=n;i++)
{
while(1)
{
int v;
scanf("%d",&v);
if(!v)
break;
s[i][v]=1;
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<i;j++)
if(!s[i][j]||!s[j][i])
{
g[i].push_back(j);
g[j].push_back(i);
}
bool is=false;
ind=0;
for(int i=1;i<=n;i++)
if(color[i]==-1)
{
color[i]=0;
cnt[++ind][0]++;
grp[i]=ind;
if(!DFS(i))
{
is=true;
break;
}
}
if(is)
printf("No solution\n");
else
solve();
if(T)
printf("\n");
}
return 0;
}