poj 2226 Muddy Fields(合理建图+二分匹配)

简介:

/*
    题意:用木板盖住泥泞的地方,不能盖住草。木板任意长!可以重叠覆盖! '*'表示泥泞的地方,'.'表示草!
    思路:
         首先让我们回忆一下HDU 2119 Matrix这一道题,一个矩阵中只有0, 1,然后让我们通过选择一行,或者
         是一列将其所在行的或者所在列的 1全部删掉,求出最少需要几步?
         
         这道题的思路就是:将行标 和 列标值为1的建立一条边!通过匈牙利算法可以得到这个二分图的最大匹配数
         最大匹配数==最小顶点覆盖数!最小顶点覆盖就是用最少的点覆盖了这个二分图的所有的边,然后去掉这些
         最小覆盖中的顶点就可以去掉所有的边,也就是所有的 1都去掉了! 
    
    那么这道题该怎么办呢?其实和上面的思路差不多,只不过是不能在原图上解题!这道题每一行或者每一列
    都有限制的因素,就是草地,覆盖泥泞的地方时不能覆盖草地,所以要想办法忽略草地的影响!
    
    解决方法:连通块的思路
       如果一个连通区域的左右两侧无法延伸则为行连通块儿,上下无法延伸则为列连通块儿,把行连通块儿作为X集合,列连通块儿作为Y集合,则X与Y相连得到的边就代表所要覆盖的       泥泞区域。即可用匈牙利算法求出覆盖所有泥泞区域所需要的最少连通块儿。
                1,现将每一行的不连在一起的泥泞土地赋给不同的编号(从1...cntR开始),也就是如果忽略
    草地的话,泥泞的地方一共有cntR个行连通块!
             2,同理每一列按照每一行的操作, 共有cntC个列连通块!
    这样结题思路就和上面的那一道题一样了..... 
            
    g[i][j]=='*' 那么aR[i][j]就是该点新的行标, aC[i][j]就是该点行的列标 
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#define M 55
#define N 1000
using namespace std;
vector<int>v[N];
char g[M][M];
int vis[N];
int linker[N];
int aR[M][M], aC[M][M]; 
int n, m;

bool dfs(int u){
   int len=v[u].size();
   for(int i=0; i<len; ++i){
       int vu=v[u][i];
       if(!vis[vu]) {
              vis[vu]=1; 
           if(!linker[vu] || dfs(linker[vu])){
               linker[vu]=u;
               return true;
           }
       }
   }
   return false;
}

int main(){
   while(scanf("%d%d", &n, &m)!=EOF){
          int cntR=1, cntC=1;
       for(int i=1; i<=n; ++i)
          scanf("%s", g[i]+1);
       for(int i=1; i<=n; ++i)
          for(int j=1; j<=m; ++j)
             if(g[i][j]=='*'){
                aR[i][j]=cntR;
                if(j+1>m || g[i][j+1]!='*')
                   ++cntR; 
             }
       for(int j=1; j<=m; ++j)
          for(int i=1; i<=n; ++i)
             if(g[i][j]=='*'){
                 aC[i][j]=cntC;
                 if(i+1>n || g[i+1][j]!='*')
                   ++cntC;
             }
       for(int i=1; i<=n; ++i)
          for(int j=1; j<=m; ++j)
            if(g[i][j]=='*')
               v[aR[i][j]].push_back(aC[i][j]);  
       
       int ans=0;
       memset(linker, 0, sizeof(linker));
       for(int i=1; i<cntR; ++i){
           memset(vis, 0, sizeof(vis));
           if(dfs(i))  ++ans;
       } 
       printf("%d\n", ans); 
       for(int i=1; i<cntR; ++i)
          v[i].clear();
   }
   return 0;
}

目录
相关文章
|
Kubernetes 监控 API
在K8S中,Minikube、Kubectl、Kubelet是什么?
在K8S中,Minikube、Kubectl、Kubelet是什么?
|
存储 网络协议 安全
阿里云国际CDN加速图文和视频类网站操作教程
阿里云国际CDN加速图文和视频类网站操作教程
|
Android开发
无法唤起支付宝APP问题分析
商家在网页中调用支付宝提供的网页支付接口调起支付宝客户端内的支付模块,商家网页会跳转到支付宝中完成支付,支付完后跳回到商家网页内,最后展示支付结果。若无法唤起支付宝客户端,则在一定的时间后会自动进入网页支付流程。
8645 12
|
机器学习/深度学习 网络协议 物联网
MQTT 协议格式 | 学习笔记
快速学习 MQTT 协议格式
MQTT 协议格式 | 学习笔记
|
存储 程序员 C#
基于C#实现的学生成绩管理系统
基于C#实现的学生成绩管理系统
358 0
学习HTML笔记17
HTML 属性
155 0
|
存储 算法 计算机视觉
使用Roberts算子进行图像分割(Matlab自编程实现)
使用Roberts算子进行图像分割(Matlab自编程实现)
553 0
使用Roberts算子进行图像分割(Matlab自编程实现)
|
人工智能 自然语言处理 供应链
案例-跟着招行年报学数字化转型
招商银行发布的2019年度报告中,详细描述了自己在金融科技方面的投入、举措和成果,可见招商银行数字化转型已初见成效,为全行业数字化转型提供了很好的借鉴意义。
1586 0
案例-跟着招行年报学数字化转型
|
存储 Oracle 关系型数据库
德哥解读:微软官宣收购PostgreSQL初创公司Citus Data
昨天在微软的官方博客官宣了微软对PostgreSQL初创公司Citus Data的收购。原文在https://blogs.microsoft.com/blog/2019/01/24/microsoft-acquires-citus-data-re-affirming-its-commitment-to-open-source-and-accelerating-azure-postgresql-performance-and-scale/?from=timeline&isappinstalled=0 背景介绍: Citus Data 2010年成立于加州旧金山。
4677 0