zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    自动控制基础MATLAB 2
    钽电容和瓷片电容的对比
    自动控制原理基础 matlab 1
    Altium使用总结1
    Altium 各个层的作用
    C语言联合体的灵活运用
    windows清除日志
    Lingo 优化实例 出版社问题
    Lingo 0-1规划
    用CMD分类
  • 原文地址:https://www.cnblogs.com/yzcstc/p/2977725.html
Copyright © 2011-2022 走看看