POJ 1112 Team Them Up! DP

来源:互联网 发布:小米数据迁移到苹果 编辑:程序博客网 时间:2024/06/06 05:34

题目大意:

现有n个人,现把他们分成两只队伍,要满足1、任何一个人有且仅属于一只队伍;2、队伍不能为空;3、队伍内的人互相认识;4、两只队伍人数尽量接近。现在给你这些人的认识关系,求一种合理的分队方式,如果没有输出No solution。


很有意思的DP,从“认识”考虑是困难的,但是两个人,如果他们不能互相认识,那么他们必然属于两个不同的组。我们用不认识的关系建边,进行奇偶染色,如果染色冲突,那么肯定无解。如果染色成功,我们可以把这个连通块的人分为两个部分。这样操作后,等于把人分为了若干类物品,每个物品有两个权。你每个物品必须选且只能选一个权,最后使得这个权和尽量接近所有权和的一半。而这个模型,是很好解决的。


#include<cstdio>#include<cstring>#include<vector>#include<queue>#include<cmath>#include<cctype>#include<string>#include<algorithm>#include<iostream>#include<ctime>#include<map>#include<set>using namespace std;#define MP(x,y) make_pair((x),(y))#define PB(x) push_back(x)typedef long long LL;//typedef unsigned __int64 ULL;/* ****************** */const int INF=100011122;const double INFF=1e100;const double eps=1e-8;const LL mod=20120427;const int NN=105;const int MM=1000010;/* ****************** */struct G{    int v,next;}E[NN*NN*2];int p[NN],T;void add(int u,int v){    E[T].v=v;    E[T].next=p[u];    p[u]=T++;}int color[NN];int lei[NN];bool mat[NN][NN];bool dp[NN][NN];int pre[NN][NN];bool xuan[NN][2];bool fg;struct node{    int x,y;}a[NN];void dfs(int u,int lll){    int i,v;    for(i=p[u];i+1;i=E[i].next)    {        v=E[i].v;        if(color[v]==-1)        {            color[v]=1-color[u];            lei[v]=lll;            if(color[v]==1)                a[lll].x++;            else                a[lll].y++;            dfs(v,lll);        }        else if(color[v]==color[u])            fg=true;    }}void FF(int tol,int zt,int n){    int i,j;    memset(xuan,false,sizeof(xuan));    j=zt;    for(i=tol;i>=1;i--)    {        if(pre[i][j]==1)        {            xuan[i][1]=true;            j=j-a[i].x;        }        else        {            xuan[i][0]=true;            j=j-a[i].y;        }    }    printf("%d",zt);    for(i=1;i<=n;i++)    {        if(xuan[ lei[i] ][ color[i] ])            printf(" %d",i);    }    puts("");    printf("%d",n-zt);    for(i=1;i<=n;i++)    {        if(!xuan[ lei[i] ][ color[i] ])            printf(" %d",i);    }    puts("");}int main(){    int n,i,j,t,tol;    while(scanf("%d",&n)!=EOF)    {        memset(p,-1,sizeof(p));        T=0;        memset(mat,false,sizeof(mat));        for(i=1;i<=n;i++)        {            while(1)            {                scanf("%d",&t);                if(t==0)break;                mat[i][t]=true;            }        }        for(i=1;i<=n;i++)            for(j=i+1;j<=n;j++)            {                if(!mat[i][j] || !mat[j][i])                {                    add(i,j);                    add(j,i);                }            }        memset(color,-1,sizeof(color));        fg=false;        tol=0;        for(i=1;i<=n && !fg;i++)        {            if(color[i]==-1)            {                tol++;                color[i]=1;                lei[i]=tol;                a[tol].x=1;                a[tol].y=0;                dfs(i,tol);            }        }        if(fg)        {            puts("No solution");            continue;        }        memset(dp,false,sizeof(dp));        dp[0][0]=true;        for(i=0;i<tol;i++)            for(j=0;j<=n/2;j++)                if(dp[i][j])                {                    dp[i+1][ j+a[i+1].x ]=true;                    pre[i+1][ j+a[i+1].x ]=1;                    dp[i+1][ j+a[i+1].y ]=true;                    pre[i+1][ j+a[i+1].y ]=0;                }        for(i=n/2;i>=1;i--)        {            if(dp[tol][i])            {                FF(tol,i,n);                break;            }        }        if(i==0)            puts("No solution");    }    return 0;}


0 0
原创粉丝点击