poj 1112

昨天晚上看的题。

说实话,我一眼就看出了是二分图,再一眼就看出了是二分图+dp(01背包)。但悲剧的是我一眼看出的算法是正确的,但我总以为它是错误的,浪费了很长时间像其他算法(TAT)。

今天终于把代码打了出来,刚开始01背包的优化后来发现是错误的,忘记删了,导致WA一次。吃晚饭时突然发现了,便AC。

2013-6-29

代码:

#include<cstdio>

#include<cstring>

using namespace std;

 

int n,col[101],w[202],m=0,dp[101][101],pre[101][101];

bool map[101][101]={0},vis[202]={0},f=0;

void dfs(int x,int cur){

         vis[x]=1,col[x]=2*m+cur;

         w[2*m+cur]++;

         for(int i=0;i<n;i++){

                   if(map[x][i] && vis[i] && col[x]==col[i]){

                            f=1;

                            return;

                   }

                   if(map[x][i] && !vis[i]){

                            dfs(i,1^cur);

                            if(f)return;

                   }

         }

         return;

}

int max(int x,int y){

         return (x>y)?x:y;

}

int min(int x,int y){

         return (x<y)?x:y;

}

int main(){

         scanf("%d",&n);

         for(int i=0;i<n;i++){

                   int x;

                   while(scanf("%d",&x),x!=0)

                            map[i][--x]=1;

         }

         for(int i=0;i<n;i++)

                   for(int j=0;j<i;j++)

                            if(map[i][j]*map[j][i]==0 && i!=j)map[i][j]=map[j][i]=1;else map[i][j]=map[j][i]=0;

         for(int i=0;i<n;i++)if(!vis[i]){

                   dfs(i,0);

                   m++;

         }

         if(f){

                   printf("No solution\n");

                   return 0;

         }

         m*=2;

         memset(dp[0],-1,sizeof(dp[0]));

         memset(vis,0,sizeof(vis));

         dp[0][0]=0;

         for(int i=1;i<=m;i+=2)

                   for(int j=0;j<=n;j++){       //这里我一开始打成了for(int j=min(w[i-1],w[i]);j<=n;j++)

                            int a=(i+1)/2;

                            dp[a][j]=-1;pre[a][j]=-1;

                            if(j>=w[i-1] && dp[a-1][j-w[i-1]]+w[i-1]>max(dp[a][j],w[i-1]-1))dp[a][j]=max(dp[a][j],dp[a-1][j-w[i-1]]+w[i-1]),pre[a][j]=2;

                            if(j>=w[i] && dp[a-1][j-w[i]]+w[i]>max(dp[a][j],w[i]-1))dp[a][j]=max(dp[a][j],dp[a-1][j-w[i]]+w[i]),pre[a][j]=1;

                   }

         int j;

         for(j=n/2;j>=0 && dp[m/2][j]==-1;j--);

         if(j<0){

                   printf("No solution\n");

                   return 0;

         }

         int j1=j;

         for(int i=m/2;i>0;i--)

                   vis[i*2-pre[i][j]]=1,j-=w[i*2-pre[i][j]];

         printf("%d",j1);

         for(int i=0;i<n;i++)

                   if(vis[col[i]])printf(" %d",i+1);

         printf("\n");

         printf("%d",n-j1);

         for(int i=0;i<n;i++)

                   if(!vis[col[i]])printf(" %d",i+1);

         printf("\n");

         return 0;

}

posted @ 2013-07-01 21:39  shanquan2  阅读(321)  评论(0编辑  收藏  举报