不认识的人间连边,对于每个连通分量dfs染色 再01背包DP就ok
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
vector<int>s[2][150];
int mp[150][150],p[150][150],vi[150],dp[150][150];
int path[150],c[150];
int t,n,cnt;
struct node
{
int x;
int va;
};
int dfs(int i,int va)
{
vi[i]=1;
c[i]=va;
s[va][cnt].push_back(i);
for(int j=1;j<=n;j++)
if(i!=j&&p[i][j])
{
if(vi[j])
{
if((c[i]%2)==(c[j]%2))
return 1;
}
else
if(dfs(j,va^1))
return 1;
}
return 0;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
cnt=0;
for(int i=0;i<2;i++)
for(int j=0;j<110;j++)
s[i][j].clear();
memset(mp,0,sizeof(mp));
memset(p,0,sizeof(p));
memset(vi,0,sizeof(vi));
memset(path,0,sizeof(path));
for(int i=1;i<=n;i++)
{
int a;
while(scanf("%d",&a)==1&&a)
mp[i][a]=1;
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
if(mp[i][j]==0||mp[j][i]==0)
p[i][j]=p[j][i]=1;
}
int ff=0;
for(int i=1;i<=n;i++)
{
if(vi[i])
continue;
cnt++;
if(dfs(i,1))
{
ff=1;
break;
}
}
if(ff)
{
printf("No solution\n");
if(t)
puts("");
continue;
}
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1;i<=cnt;i++)
{
for(int j=n/2;j>=0;j--)
{
if(dp[i-1][j])
{
dp[i][j+s[0][i].size()]=1;
dp[i][j+s[1][i].size()]=2;
}
}
}
int sum;
for(sum=n/2;sum>=0;sum--)
{
if(dp[cnt][sum])
break;
}
int index=0;
for(int i=cnt;i>=1;i--)
{
if(dp[i][sum]==1)
{
sum-=s[0][i].size();
for(int j=0;j<s[0][i].size();j++)
path[++index]=s[0][i][j];
}
else
{
sum-=s[1][i].size();
for(int j=0;j<s[1][i].size();j++)
path[++index]=s[1][i][j];
}
}
memset(vi,0,sizeof(vi));
printf("%d",index);
for(int i=1;i<=index;i++)
{
printf(" %d",path[i]);
vi[path[i]]=1;
}
puts("");
printf("%d",n-index);
for(int i=1;i<=n;i++)
{
if(!vi[i])
printf(" %d",i);
}
puts("");
if(t)puts("");
}
return 0;
}