二分图最大匹配 hdoj 1045「建议收藏」

二分图最大匹配 hdoj 1045

大家好,又见面了,我是全栈君。

题目:hdoj1045

题意:给出一个图。当中有 . 和 X 两种,. 为通路,X表示墙,在当中放炸弹,然后炸弹不能穿过墙。问你最多在图中能够放多少个炸弹?

分析:这道题目是在上海邀请赛的题目的数据简化版。数据水了,所以有非常多方法,这里讲二分图最大匹配,题目难点在于建图

想到用暴力过。可是事实证明我想多了。

然后又想到多重二分匹配,后来发现没有办法表示图中的行列中墙的阻隔,后来看了别人的建图,瞬间认为高大上。

建图,首先把每一行中的能够放一个炸弹的一块区域标记为同一个数字。数字不反复,然后列做同样的处理,即缩点。

缩点之后原图矩阵中每一个点都对用一个行数字和一个列数字,然后依照这两个数字进行二分匹配,其同样值仅仅取一个,得到的结果就是ans;

注意:每次推断增广的时候首先检查一下当前点有没有匹配。假设匹配就不用搜索,由于有多个值相应一个点,所以…

代码:

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 10;
#define Del(x,y) memset(x,y,sizeof(x))
char map[N][N];
int path[N][N];
int line[N][N],row[N][N],link[N],vis[N],vlink[N];
int n,cnt_row,cnt_line;
bool dfs(int x)
{
    for(int i=0;i<cnt_line;i++)
    {
        if(path[x][i]==1 && vis[i]==0)
        {
            vis[i]=1;
            if(link[i]==-1 || dfs(link[i]))
            {
                link[i]=x;
                vlink[x]=i;
                return true;
            }
        }
    }
    return false;
}
void solve()
{
    int ans=0;
    Del(link,-1);
    Del(vlink,-1);
    for(int i=0;i<cnt_row;i++)
    {
        if(vlink[i]==-1){  ///注意!标记找过的
            Del(vis,0);
            if(dfs(i))
                ans++;
        }
    }
    printf("%d\n",ans);
}
int main()
{
    //freopen("Input.txt","r",stdin);
    while(~scanf("%d",&n) && n)
    {
        char c;
        Del(map,0);
        for(int i=0;i<n;i++)
        {
            getchar();
            for(int j=0;j<n;j++)
                scanf("%c",&map[i][j]);
        }
        Del(line,-1);
        Del(row,-1);
        cnt_row=0,cnt_line=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(map[i][j] == '.' && row[i][j] == -1)
                {
                    for(int k = j; map[i][k] == '.' && k < n; ++k)
                        row[i][k] = cnt_row;
                    cnt_row++;
                }
                if(map[j][i] == '.' && line[j][i] == -1)
                {
                    for(int k = j; map[k][i] == '.' && k < n; ++k)
                        line[k][i] = cnt_line;
                    cnt_line++;
                }
            }
        }
        Del(path,0);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(map[i][j]=='.')
                    path[row[i][j]][line[i][j]]=1;
            }
        }
        solve();
    }
    return 0;
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/116075.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 二维数组赋值 java_java二维数组的赋值方法「建议收藏」

    二维数组赋值 java_java二维数组的赋值方法「建议收藏」在java数组中,我们想要知道其长度,可以通过赋值的方法来实现。在正式开始对数组赋值前,我们要明确其中的下标问题。在准备步骤上,先找到高维的位置,再确定低纬的下标,就可以进行相关的赋值操作了。下面就具体的二维数组赋值,我们先简单分析赋值的概念,然后带来具体的赋值实例。1.赋值概念使用双下标访问二维数组中的元素:第一个下标代表:行号(高维下标)。第二个下标代表:列号(低维下标)。2.赋值实例(1)赋…

    2022年5月6日
    156
  • c语言和java哪个有前途_Java和C语言哪个好就业?

    c语言和java哪个有前途_Java和C语言哪个好就业?编程语言多达600余种,有畅行多年的,有逐渐被人遗忘的,还有发展迅速的后起之秀。Java和C语言作为使用者较多的两大语言,受到很多编程初学者的青睐,很多人在Java和C语言之间不知道该选哪个,想从事软件开发工作的话,究竟学哪个好呢?从两者的起源来看,Java是C语言的后辈,它是在C语言的基础上发展得来,抛弃了难懂的指针概念,和C完全不同的是Java是一门面向对象的语言,因为Java的跨平台和可移植…

    2022年7月16日
    14
  • 作为一个程序员,什么是脚本。必须要理解「建议收藏」

    作为一个程序员,什么是脚本。必须要理解「建议收藏」Javascript是一门动态类型、面向对象的脚本语言。对脚本进行一个感性的认识。就是一个跟计算机执行的文本。理解脚本如果你打开一本JavaScript教程,那么很可能在第一章就看到这句话

    2022年8月2日
    2
  • 配置 PyCharm for Linux 设置启动图标 pycharm-edu-2021.3.1 Ubuntu 18.04.6 LTS

    配置 PyCharm for Linux 设置启动图标 pycharm-edu-2021.3.1 Ubuntu 18.04.6 LTS安装PyCharm下载PyCharm教育版,使用tar-zxvf命令将其解压到你希望的软件安装位置,解压完就是安装完了,要选择一个你有全部权限的目录,一般在自己家目录下挑选位置即可。cd到安装目录下,执行以下命令运行PyCharm,第一次运行会有一些选择内容,按实际选择即可。cdbin/./pycharm.sh安装完成!自定义图标固定到收藏夹在下面两个路径中任选,创建matlab.desktop文件。前者是系统全局的,后者是当前用户私有的/usr/share/appl

    2022年10月22日
    0
  • 【Java】深入理解Java随机数

    【Java】深入理解Java随机数本文介绍Java随机数的内容

    2022年7月26日
    5
  • POJ 2478 Farey Sequence

    POJ 2478 Farey Sequence

    2021年11月29日
    44

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号