poj1112 Team Them Up!

来源:互联网 发布:android锁机源码 编辑:程序博客网 时间:2024/05/22 10:58
/* * poj1112 AC * DP 背包问题 与poj1636 prison rearrangement如出一辙。 * 问题挺经典,重点在于构造模型。 * 首先考虑将所有人分为互斥的若干部分,这便是背包问题中物品了。 * 之后,要将每个"物品"分为放在A和放在B的两个部分,然后进行DP。 * * I. 求补图,将表示两个人相互认识的边去除,连接所有互相不认识, *    或单方面认识的边。 * II.对每个处于同一连通分量的人进行染色,同时将每一个联通分量 *    构造成类似于二分图的形式,分为两个部分。 *III.类似与poj1636的方式进行DP,每个“物品”分为两种放法,想象一 *    下堆积木,得到最小的差值,记录下选择的路径。 * * 注意:不要MLE了,使用char来替代short。 * * */#include<cstdio>#include<algorithm>#include<memory.h>using namespace std;int n,tot;bool map[105][105],flag,dp[105][105][105];int node[10005],next[10005],head[105];short a[105][2],label[105]; char pre[105][105][105][4],rec[105][105][105],fir[105],sec[105],col[105];void addnode(int x,int y){    node[++tot] = y,next[tot] = head[x],head[x] = tot;}//void dfs(int x,int team)void dfs(char x,int team){    a[tot][team]++,rec[tot][team][a[tot][team]] = x,label[(int)x] = tot,col[(int)x] = team;    int i;    for(i=head[(int)x];i;i=next[i])    {        if(label[node[i]]==0)        {            dfs(node[i],1-team);            if(!flag) return;        }else if(label[node[i]]==label[(int)x] && col[node[i]]==col[(int)x])        {            flag = false;            return;        }    }    return;}int main(){    scanf("%d",&n);//    FILE* fin = fopen("d.in","r");//    fscanf(fin,"%d",&n);    int i,j,k;    memset(map,false,sizeof(map));    for(i=1;i<=n;i++)    {        while(scanf("%d",&j) && j)//        while(fscanf(fin,"%d",&j) && j)            map[i][j] = true;    }    for(i=1;i<=n;i++)        for(j=i;j<=n;j++)        {            if(map[i][j] && map[j][i])                map[i][j] = map[j][i] = false;            else                 map[i][j] = map[j][i] = true;        }        memset(head,0,sizeof(head));    memset(next,0,sizeof(next));    memset(node,0,sizeof(node));    for(tot=0,i=1;i<=n;i++)        for(j=1;j<=n;j++)            if(i!=j && map[i][j])                addnode(i,j);    memset(col,0,sizeof(col));    memset(label,0,sizeof(label));    for(tot=0,flag=true,i=1;i<=n;i++)        if(label[i]==0)         {            tot++;            dfs(i,0);            if(!flag) break;        }    if(!flag)        printf("No solution\n");    else     {        memset(pre,0,sizeof(pre));        memset(dp,false,sizeof(dp));        dp[0][0][0] = true;        for(i=1;i<=tot;i++)            for(j=n;j>=0;j--)                for(k=n;k>=0;k--)                {                    if(j-a[i][0]>=0 && k-a[i][1]>=0)                    {                        if(dp[i-1][j-a[i][0]][k-a[i][1]])                        {                            dp[i][j][k] = true;                            pre[i][j][k][0] = j-a[i][0];                            pre[i][j][k][1] = k-a[i][1];                            pre[i][j][k][2] = 0;                        }                    }                    if(j-a[i][1]>=0 && k-a[i][0]>=0)                    {                        if(dp[i-1][j-a[i][1]][k-a[i][0]])                        {                            dp[i][j][k] = true;                            pre[i][j][k][0] = j-a[i][1];                            pre[i][j][k][1] = k-a[i][0];                            pre[i][j][k][2] = 1;                        }                    }                }        int num1,num2,min = 0xffff;         for(i=1;i<=n;i++)            for(j=1;j<=n;j++)                if(dp[tot][i][j] && abs(i-j)<min)                    num1 = i,num2 = j,min = abs(i-j);        int tot1,tot2;        for(tot1=tot2=0,i=tot;i>0;i--)        {            if(pre[i][num1][num2][2]==0)            {                for(j=1;j<=a[i][0];j++)                    fir[++tot1] = rec[i][0][j];                for(j=1;j<=a[i][1];j++)                    sec[++tot2] = rec[i][1][j];            }else if(pre[i][num1][num2][2]==1)            {                for(j=1;j<=a[i][1];j++)                    fir[++tot1] = rec[i][1][j];                for(j=1;j<=a[i][0];j++)                    sec[++tot2] = rec[i][0][j];            }            int t = num1;            num1 = pre[i][num1][num2][0];            num2 = pre[i][t][num2][1];        }        sort(fir+1,fir+tot1+1);        sort(sec+1,sec+tot2+1);        printf("%d ",tot1);        for(i=1;i<=tot1;i++)            printf("%d ",fir[i]);        printf("\n%d ",tot2);        for(i=1;i<=tot2;i++)            printf("%d ",sec[i]);        printf("\n");    }    return 0;}

原创粉丝点击