zoj1462 二分图染色+DP

来源:互联网 发布:js中的event对象 编辑:程序博客网 时间:2024/05/02 04:34
不认识的人间连边,对于每个连通分量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;}elseif(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;}