• BZOJ 1735: [Usaco2005 jan]Muddy Fields 泥泞的牧场


    Description

        大雨侵袭了奶牛们的牧场.牧场是一个R * C的矩形,其中1≤R,C≤50.大雨将没有长草的土地弄得泥泞不堪,可是小心的奶牛们不想在吃草的时候弄脏她们的蹄子.  为了防止她们的蹄子被弄脏,约翰决定在泥泞的牧场里放置一些木板.每一块木板的宽度为1个单位,长度任意.每一个板必须放置在平行于牧场的泥地里.    约翰想使用最少的木板覆盖所有的泥地.一个木板可以重叠在另一个木板上,但是不能放在草地上.

    Input

    第1行:两个整数R和C.

    第2到R+1行:每行C个字符,其中“*’代表泥地,“.”代表草地.

    Output

    最少需要多少木板.

    题解:

    •不能盖住好地,那么宽为1的木板只能放在行、列连通块里。

    •所以行、列连通块对应左、右部中的点,泥地对应边。

    •求二分图最小覆盖就是答案。

    二分图最小点覆盖==最大匹配

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    //by zrt
    //problem:
    using namespace std;
    typedef long long ll;
    const double eps(1e-10);
    int R,C,n;
    char s[60][60];
    int link[1005];
    int cover[1005];
    int H[1005],X[1000050],P[1000050],tot;
    inline void add(int x,int y){
        P[++tot]=y;X[tot]=H[x];H[x]=tot;
    }
    bool find(int x){
        for(int i=H[x];i;i=X[i]){
            if(cover[P[i]]) continue;
            cover[P[i]]=1;
            int q=link[P[i]];
            link[P[i]]=x;
            if(q==-1||find(q)) return 1;
            link[P[i]]=q;
        }
        return 0;
    }
    int xn,yn;
    int a[60][60],b[60][60];
    int main(){
        #ifdef LOCAL
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
        #endif
        memset(link,-1,sizeof link);
        scanf("%d%d",&R,&C);
        for(int i=0;i<R;i++){
            scanf("%s",s[i]);
        }
        for(int i=0;i<R;i++){
            for(int j=0;j<C;j++){
                if(s[i][j]=='*'){
                    if(j>0&&s[i][j-1]=='*'){
                        a[i][j]=a[i][j-1];
                    }else a[i][j]=++yn;
                    if(i>0&&s[i-1][j]=='*'){
                        b[i][j]=b[i-1][j];
                    }else b[i][j]=++xn;
                }
            }
        }
        for(int i=0;i<R;i++){
            for(int j=0;j<C;j++){
                if(s[i][j]=='*'){
                        add(a[i][j],b[i][j]);
                }
            }
        }
        n=yn;
        int ans(0);
        for(int i=1;i<=n;i++){
            memset(cover,0,sizeof cover);
            if(find(i)) ans++;
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    将java库转换为.net库(转载)
    web sql设计器(连接)
    [SQLSERVER]SQL中的全文检索(转邹建)
    网络最经典命令行-网络安全工作者的必杀技
    无效的 CurrentPageIndex 值。它必须大于等于 0 且小于 PageCount。
    06毕业设计 VB导出Excel文档
    06毕业设计 VB导出word文档
    C# 交替显示项的DataGird,鼠标上移时转变颜色,退出后能恢复原来颜色
    js.offsetParent属性
    自动提醒IE6访客升级浏览器,
  • 原文地址:https://www.cnblogs.com/zrts/p/bzoj1735.html
Copyright © 2020-2023  润新知