poj 1636 好题》

来源:互联网 发布:铁观音 淘宝推荐 编辑:程序博客网 时间:2024/05/18 02:14

题意:

两个人数一样的监狱,有一些囚犯不能在一起,两个监狱要等数量( < m/2)交换一些囚犯,问最多可以交换多少个囚犯;

分析:
由题意可知,会有一些联通的块需要同时移动,那我们就把这些联通块求出来,统计一下各个监狱的人数。

然后就变成了 有 z个 联通块 可以选择换还是不换。

就变成了01背包判可行性的问题!

但是 WA的很惨烈。

这里写图片描述
没有山调试,
清空不彻底

#include<cstdio>#include<algorithm>#include<cstring>#include<vector>//by mars_chusing namespace std;int t;int m,r;vector<int> G[505];int vis[505],q[505],p[505],tot;int f[1005][1005];void dfs(int x){    if(x<=m) p[tot]++;    else q[tot]++;    vis[x]=1;    for(int i=0;i<G[x].size();i++)    {        if(!vis[G[x][i]])        {            dfs(G[x][i]);         }     }}int main(){    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&m,&r);        for(int i=0;i<=m*2;i++)        {            G[i].clear();        }        memset(vis,0,sizeof(vis));        memset(f,0,sizeof(f));        memset(p,0,sizeof(p));        memset(q,0,sizeof(q));        for(int i=1;i<=r;i++)        {            int a,b;            scanf("%d%d",&a,&b);            G[a].push_back(b+m);            G[b+m].push_back(a);        }        tot=0;        for(int i=1;i<=2*m;i++)        {            if(!vis[i])            {                tot++;                dfs(i);            }         }          int n=m/2;        f[0][0]=1;         for(int i=1;i<=tot;i++)        {            for(int j=n;j>=p[i];j--)            {                for(int k=n;k>=q[i];k--)                {                    if(f[j-p[i]][k-q[i]]) f[j][k]=1;                }            }        }        for(int i=n;i>=0;i--)        {            if(f[i][i]) {            printf("%d\n",i);            break;        }        }    }    return 0;}
0 0