poj1636

题目大意:给出两侧分别有m个节点的图,边不可能存在于同一侧的点之间.从左和右侧分别挑出数量相等且不大于m/2个一些点,进行交换,使换完后不存在同一侧的边。求最大交换点的数。。

思路:进行联通二分图染色。。颜色相同的点必须同时交换。。不然就有边处于同一测。。

        然后dp

       f[i][j]表示一个交换i个,一个个交换j个是否可行

      f[i][j] =f[i - vx[k]][j - vy[k]]|| f[i-vy[k]][j - vx[k]];

      vx[k],vy[k]表示联通块的相同颜色的个数

 1 /*
 2  Time:2013-03-07 00:50:09
 3  State:Accepted
 4 */
 5 #include <iostream>
 6 #include <cstring>
 7 #include <string>
 8 #include <cstdlib>
 9 #include <cstdio>
10 #include <vector>
11 #include <cmath>
12 #include <algorithm>
13 #define CLR(NAME) memset(NAME , 0 ,sizeof(NAME))
14 using namespace std;
15 int test , m ,r , e[410][210] , sum[3] ,vx[210] ,vy[210] , bo[410] ,tot , f[210][210];
16 void init(){
17      int x , y ;
18      scanf("%d%d",&m ,&r);
19      CLR(e);  CLR(f);
20      CLR(bo); CLR(vx);  CLR(vy);
21      for (int i = 1 ; i <= r; ++i){
22           scanf("%d%d", &x ,&y);
23           y += 200;
24           ++e[x][0]; 
25           ++e[y][0];
26           e[x][e[x][0]] = y;
27           e[y][e[y][0]] = x;
28      }
29 }
30 
31 void dfs(int node){
32      if (bo[node]) return;
33      bo[node] = 1;
34      if (node <= 200) ++sum[0];
35      else ++sum[1];
36      for (int i = 1; i <= e[node][0]; ++i)
37         dfs(e[node][i]);
38 }
39 
40 void solve(){
41      tot = 0;
42      for (int i = 1; i <= m; ++i )
43       if (!bo[i]){
44           sum[0] = sum[1] = 0; 
45           dfs(i);
46           vx[++ tot] = sum[0];
47           vy[tot] =  sum[1];
48      }
49      for (int i = 201; i <= m + 200; ++i)
50       if (!bo[i]){
51           sum[0] = sum[1] = 0; 
52           dfs(i);
53           vx[++ tot] = sum[0];
54           vy[tot] =  sum[1];
55      }
56      
57 
58      
59      f[0][0] = 1;
60      
61      for (int k = 1; k <= tot; ++k)
62          for (int i = m / 2 ; i >= vx[k] ; --i)
63              for (int j = m / 2 ; j >= vy[k]; --j)
64                      f[i][j] = f[i][j] | f[i - vx[k]][j - vy[k]];
65                      
66      for (int i = m / 2 ; i >= 0; --i)
67           if (f[i][i]){
68                     printf("%d\n",i);
69                     return;             
70           }
71      
72      
73      
74 }
75 
76 int main(){
77      freopen("poj1636.in","r",stdin);
78      freopen("poj1636.out","w",stdout);
79      scanf("%d",&test);
80      for (int i = 1; i <= test ; ++i){
81           init();
82           solve();
83      }
84      fclose(stdin); fclose(stdout);
85 }

 

posted on 2013-03-23 21:15  yzcstc  阅读(358)  评论(0编辑  收藏  举报