POJ 1636

题意:

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

根据条件可以画出一个二分图,接着可以由二分图得到的若干个连通分量。而当你选中一个囚犯的时候,因为约束条件,整个的连通分量都会受到牵连,

即这个囚犯所在的连通分量的所有囚犯都要交换。设p[i],q[i]分别为这次选取的a,b监狱中所取囚犯个数;

就可转化为背包问题;

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <string.h>
 4 using namespace std;
 5 const int M=202;
 6 bool rel[M][M],a[M],b[M],dp[M][M];
 7 int p[M],q[M];
 8 int n,m,r,aa,bb;
 9 void dfs(int i,int k){
10     if(k){
11         a[i]=1;
12         aa++;
13         for(int j=1;j<=m;j++){
14             if(rel[i][j]&&!b[j]){
15                 dfs(j,0);
16             }
17         }
18     }
19     else {
20         b[i]=1;
21         bb++;
22         for(int j=1;j<=m;j++){
23             if(rel[j][i]&&!a[j]){
24                 dfs(j,1);
25             }
26         }
27     }
28 }
29 int main(){
30     int x,y;
31     scanf("%d",&n);
32     while(n--){
33         int i;
34         memset(rel,0,sizeof(rel));
35         memset(dp,0,sizeof(dp));
36         memset(a,0,sizeof(a));
37         memset(b,0,sizeof(b));
38         scanf("%d%d",&m,&r);
39         for(i=0;i<r;i++){
40             scanf("%d%d",&x,&y);
41             rel[x][y]=1;
42         }
43         int t=0;
44         for(i=1;i<=m;++i){
45             if(!a[i]){
46                 aa=bb=0;
47                 dfs(i,1);
48                 p[t]=aa;
49                 q[t++]=bb;
50             }
51         }
52         for(i=1;i<=m;++i){
53             if(!b[i]){
54                 aa=bb=0;
55                 dfs(i,0);
56                 p[t]=aa;
57                 q[t++]=bb;
58             }
59         }
60         dp[0][0]=1;
61         for(i=0;i<t;++i){
62             for(int j=m/2;j>=p[i];--j){
63                 for(int k=m/2;k>=q[i];--k){
64                     if(dp[j-p[i]][k-q[i]]){dp[j][k]=1;}
65                 }
66             }
67         }
68         for(i=m/2;i>=0;--i)if(dp[i][i]){break;}
69         printf("%d\n",i);
70     }
71     return 0;
72 }

 

posted @ 2015-01-20 11:46  Mr.XuJH  阅读(939)  评论(0编辑  收藏  举报