poj 1636 Prison rearrangement

来源:互联网 发布:python y=lnx图像 编辑:程序博客网 时间:2024/06/04 17:50

题目链接:http://poj.org/problem?id=1636

题目大意及思路:两个监狱交换囚犯,但有些囚犯不能在同一个监狱,问最接近m/2的交换数,做法是先求连通分量和两个监狱分别的人数,没有关联的人则为(0,1)和(1,0);最后dp,求得最接近m/2的i 满足dp[i][i]=1。

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<string>#include<queue>#include<algorithm>#include<vector>#include<stack>#include<list>#include<iostream>#include<map>using namespace std;#define inf 0x3f3f3f3f#define Max 110int max(int a,int b){return a>b?a:b;}int min(int a,int b){return a<b?a:b;}struct node{    int next,to;}e[2*210*210];int cnt;int num1[210],num2[210],num[210],eid,p[410],vst[410],dp[210][210];int t,n,m;inline void addedge(int u,int v){    e[eid].to=v;    e[eid].next=p[u];    p[u]=eid++;}void dfs(int u){    int i,v;    vst[u]=1;    if(u<=m)        num1[cnt]++;    else        num2[cnt]++;    for(i=p[u];i!=-1;i=e[i].next)    {        v=e[i].to;        if(vst[v])            continue;        dfs(v);    }}int main(){    int i,j,k,u,v;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&m,&n);        eid=0,cnt=1;        memset(p,-1,sizeof(p));        memset(vst,0,sizeof(vst));        memset(dp,0,sizeof(dp));     //   memset(num,0,sizeof(num));        memset(num1,0,sizeof(num1));        memset(num2,0,sizeof(num2));        while(n--)        {            scanf("%d%d",&u,&v);            addedge(u,v+m);            addedge(v+m,u);        }        int rec=0;        for(i=1;i<=2*m;i++)        {            if(!vst[i])            {             //   printf("i %d\n",i);                dfs(i);             //   num[cnt]=max(num1[cnt],num2[cnt]);                cnt++;            }        }        dp[0][0]=1;        for(i=1;i<cnt;i++)        {         //   printf("i %d num %d\n",i,num[i]);            for(j=m/2;j>=0;j--)            {                for(k=m/2;k>=0;k--)                {                    if(j-num1[i]>=0&&k-num2[i]>=0&&dp[j-num1[i]][k-num2[i]])                        dp[j][k]=1;                }            }        }        for(j=m/2;j>=0;j--)        {            if(dp[j][j])            {                printf("%d\n",j);                break;            }        }    }}


 

原创粉丝点击