• [POJ] 2226 Muddy Fields(二分图最小点覆盖)


    题目地址:http://poj.org/problem?id=2226

    二分图的题目关键在于建图。因为“*”的地方只有两种木板覆盖方式:水平或竖直,所以运用这种方式进行二分。首先按行排列,算出每个"*"的序号xi,再按列排序,算出序号yi。

    从X集合向Y集合连边。G[xi][yi]=1; 然后就是求二分图的最小顶点覆盖。因为二分图最小点覆盖=最大匹配数。所以匈牙利算法求一下最大匹配就可以了。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<string.h>
      4 #include<algorithm>
      5 #include<math.h>
      6 #include<stdbool.h>
      7 #include<time.h>
      8 #include<stdlib.h>
      9 #include<set>
     10 #include<map>
     11 #include<stack>
     12 #include<queue>
     13 #include<vector>
     14 using namespace std;
     15 #define clr(x,y)    memset(x,y,sizeof(x))
     16 #define sqr(x)      ((x)*(x))
     17 #define rep(i,a,b)  for(int i=(a);i<=(b);i++)
     18 #define LL          long long
     19 #define INF         0x3f3f3f3f
     20 #define A           first
     21 #define B           second
     22 #define PI          acos(-1.0)
     23 const int N=1000+131;
     24 int n,m,k,k1,k2,f[N],g[N][N],c1[N][N],c2[N][N],link[N],flag[N][N];
     25 
     26 void init()
     27 {
     28     clr(f,0);
     29     clr(g,0);
     30     clr(link,-1);
     31     clr(flag,0);
     32     clr(c1,0);
     33     clr(c2,0);
     34     k1=0;k2=0;
     35 }
     36 
     37 bool find(int x)
     38 {
     39     for(int i=1;i<=k2;i++) {
     40         if(!f[i] && g[x][i]) {
     41             f[i]=1;
     42             if(link[i]==-1 || find(link[i])) {
     43                 link[i]=x;
     44                 return true;
     45             }
     46         }
     47     }
     48     
     49     return false;
     50 }
     51 
     52 int hungary()
     53 {
     54     int ans=0;
     55     for(int i=1;i<=k1;i++) {
     56         clr(f,0);
     57         if(find(i)) ans++;
     58     }
     59     return ans;
     60 }
     61 
     62 int main()
     63 {
     64     int u,v;
     65     char a[100];
     66 
     67     init();
     68     scanf("%d%d",&m,&n);
     69     getchar();
     70     for(int i=1;i<=m;i++) {
     71         scanf("%s",a+1);
     72         for(int j=1;j<=n;j++) {
     73             if(a[j]=='*') flag[i][j]=1;
     74         }
     75     }
     76     
     77     for(int i=1;i<=m;i++) {
     78         for(int j=1;j<=n;j++) {
     79             if(!flag[i][j]) continue;
     80             if(!flag[i][j-1]){
     81                 c1[i][j]=++k1;
     82             } else {
     83                 c1[i][j]=k1;
     84             }
     85         }
     86     }
     87     
     88     for(int i=1;i<=n;i++) {
     89         for(int j=1;j<=m;j++) {
     90             if(!flag[j][i]) continue;
     91             if(!flag[j-1][i]) {
     92                 c2[j][i]=++k2;
     93             } else {
     94                 c2[j][i]=k2;
     95             }
     96         }
     97     }
     98     
     99    for(int i=1;i<=m;i++){
    100         for(int j=1;j<=n;j++) {
    101             g[c1[i][j]][c2[i][j]]=1;
    102         }
    103    }
    104    
    105    printf("%d
    ",hungary()); 
    106     
    107     return 0;
    108 }
  • 相关阅读:
    多项式牛顿迭代
    小明A+B
    分拆素数和
    选课时间
    今年暑假不AC
    Lowest Common Multiple Plus
    大小写转换问题(java程序)
    VS 中输入带空格的两个字符串
    整除的尾数
    不要62
  • 原文地址:https://www.cnblogs.com/sxiszero/p/4387482.html
Copyright © 2020-2023  润新知