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 }