【DP】poj1636

来源:互联网 发布:阿里云快照收费吗 编辑:程序博客网 时间:2024/06/17 22:30

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<cmath>#include<cstdlib>using namespace std;int link[1100],n,tmp_1,tmp_2,tail,m,tot,f[510][4];bool flag[410][310],flag_point[1100];struct rec{int num,next;}e[100100];void insert (int x,int y){e[++tot].num=y;e[tot].next=link[x];link[x]=tot;}void dfs(int x){if (x<=n) tmp_1++;else tmp_2++;flag_point[x]=true;for (int p=link[x];p!=0;p=e[p].next)if (flag_point[e[p].num]==false)dfs(e[p].num);}int main(){int t,now,x,y;scanf("%d",&t);while (t--){memset(flag,0,sizeof(flag));memset(flag_point,0,sizeof(flag_point));memset(link,0,sizeof(link));memset(e,0,sizeof(e));memset(f,0,sizeof(f));tail=0;tot=0;scanf("%d%d",&n,&m);for (int i=1;i<=m;i++){scanf("%d%d",&x,&y);insert(x,y+n);insert(y+n,x);}for (int i=1;i<=2*n;i++)if (flag_point[i]==false){tmp_1=0;tmp_2=0;dfs(i);f[++tail][1]=tmp_1;f[tail][2]=tmp_2;}flag[0][0]=true;for (int i=1;i<=tail;i++)    for (int j=(n+1)/2;j>=f[i][1];j--)        for (int k=(n+1)/2;k>=f[i][2];k--)              if (flag[j-f[i][1]][k-f[i][2]])                flag[j][k]=true;for (int i=n/2;i>=0;i--)    if (flag[i][i])    {                printf("%d\n",i);                break;            }}return 0;}

题目大意:    两个监狱要交换囚犯,然而有一些第一监狱的囚犯不能与第二监狱的囚犯在一起,请问最大能交换多少个,交换次数小于n/2;

思路非常巧妙,把相互之间有不能见关系的人看成一个物品,f[i][1]代表其中第一个监狱的人数,f[i][2]代表第二监狱人数。然后flag[i][j]表示有i个本来在第一监狱现在在第二监狱,

有j个本来在第二监狱现在在第一监狱,然后i==j的话就可以是一个最终状态、


代码如下:

0 0
原创粉丝点击