(点击此处查看原题)

匈牙利算法简介

个人认为这个算法是一种贪心+暴力的算法,对于二分图的两部X和Y,记x为X部一点,y为Y部一点,我们枚举X的每个点x,如果Y部存在匹配的点y并且y没有被其他的x匹配,那就直接匹配;如果Y中已经没有可以和x匹配的点(包括可以匹配的点已经被其他的x匹配),那就让已经匹配的y的原配x'寻找其他可以匹配的y’,并将y和x匹配,最后,统计出匹配的对数

(详细了解的话,可以看看这位的博客:https://blog.csdn.net/sunny_hun/article/details/80627351

题意

在一个n*n的网格中,存在一些墙壁,用'X‘表示,我们需要摆放blockhouse,由于每个blockhouse会向四周发射子弹,所以任意两个blockhouse不能在一条直线上,除非他们之间有墙壁分隔,问在给定的网格中,最多可以摆放多少个blockhouse

解题思路

(一开始我想用深搜暴力写的,过了样例,但是WA了,觉得自己的暴力写法没什么问题的,但是一直过不了,就只能放弃暴力了)

注意到如果我们在每个点放置了blockhouse,那么这个blockhouse向四个方向延申至墙壁或者边界,这个blockhouse可以视作是由一段连续的横区间和纵区间的交点,如下图所示:

因此,我们发现,连续的纵横区间的交点形成一个blockhouse,并使得这两个区间都无法放置其他的blockhouse,由此看出这是一个求二分图最大匹配的问题

我们将连续的纵区间当作一个点,作为X部,将练习的横区间当作一个点,作为Y部,对于相交的横纵区间,我们由纵区间代表的点向横坐标代表的点建边,构建二分图

随后我们可以通过将二分图转化使用最大流求解,也可以用匈牙利算法求解,由于Dinic算法代码量冗长,这里就采用了匈牙利算法求解

代码区

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<string>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#include <iomanip> #define bug cout << "**********" << endl
#define show(x, y) cout<<"["<<x<<","<<y<<"] "
#define LOCAL = 1;
using namespace std;
typedef long long ll;
const int inf = 1e7 + ;
const ll mod = 1e9 + ;
const int Max = 1e6 + ;
const int Max2 = 3e2 + ; int n;
char mp[][];
int row_id[][], col_id[][], cnt_row, cnt_col; //记录每个点所处的行、列编号
bool edge[][], vis[]; //代表是否配对以及是否已经占用
int match[]; bool dfs(int x)
{
for (int i = ; i < cnt_col; i++)
{
if (edge[x][i] && !vis[i])
//used表示曾试图改变i的匹配对象,但是没有成功的话(used[i]= true),所以就无需继续
{
vis[i] = true;
if (match[i] == - || dfs(match[i])) //i没有匹配对象,或者i原来的匹配对象还可以和其他的匹配
{
match[i] = x;
return true;
}
}
}
return false;
} int solve()
{
int res = ;
memset(match, -, sizeof(match));
for (int i = ; i < cnt_row; i++)
{
memset(vis, , sizeof(vis));
if (dfs(i))
res++;
}
return res;
} int main()
{
#ifdef LOCAL
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
while (scanf("%d", &n) != EOF && n)
{
cnt_row = cnt_col = ;
memset(edge, , sizeof(edge)); for (int i = ; i <= n; i++)
{
scanf("%s", mp[i] + );
} for (int i = ; i <= n; i++)
{
for (int j = ; j <= n; j++)
{
if (mp[i][j] == '.')
{
int u = , v = ;
if (j == || mp[i][j - ] == 'X')
u = cnt_row++;
else
u = row_id[i][j - ]; if (i == || mp[i - ][j] == 'X')
v = cnt_col++;
else
v = col_id[i - ][j]; edge[u][v] = true; row_id[i][j] = u;
col_id[i][j] = v;
}
}
}
printf("%d\n", solve());
}
return ;
}

题外延申

匈牙利算法复杂度O(VE)

最小点覆盖=最大匹配数

最小边覆盖=左右点数-最大匹配数

最小路径覆盖=点数-最大匹配数

最大独立集=点数-最大匹配数

HDU - 1045 Fire Net (二分图最大匹配-匈牙利算法)的更多相关文章

  1. hdu 2063 过山车 (最大匹配 匈牙利算法模板)

    匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最 ...

  2. HDU 1045 - Fire Net - [DFS][二分图最大匹配][匈牙利算法模板][最大流求二分图最大匹配]

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1045 Time Limit: 2000/1000 MS (Java/Others) Mem ...

  3. UESTC 919 SOUND OF DESTINY --二分图最大匹配+匈牙利算法

    二分图最大匹配的匈牙利算法模板题. 由题目易知,需求二分图的最大匹配数,采取匈牙利算法,并采用邻接表来存储边,用邻接矩阵会超时,因为邻接表复杂度O(nm),而邻接矩阵最坏情况下复杂度可达O(n^3). ...

  4. Ural1109_Conference(二分图最大匹配/匈牙利算法/网络最大流)

    解题报告 二分图第一题. 题目描写叙述: 为了參加即将召开的会议,A国派出M位代表,B国派出N位代表,(N,M<=1000) 会议召开前,选出K队代表,每对代表必须一个是A国的,一个是B国的; ...

  5. HDU1068 (二分图最大匹配匈牙利算法)

    Girls and Boys Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  6. HDU 1045——Fire Net——————【最大匹配、构图、邻接矩阵做法】

    Fire Net Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Sta ...

  7. poj - 3041 Asteroids (二分图最大匹配+匈牙利算法)

    http://poj.org/problem?id=3041 在n*n的网格中有K颗小行星,小行星i的位置是(Ri,Ci),现在有一个强有力的武器能够用一发光速将一整行或一整列的小行星轰为灰烬,想要利 ...

  8. 二分图最大匹配(匈牙利算法) POJ 3041 Asteroids

    题目传送门 /* 题意:每次能消灭一行或一列的障碍物,要求最少的次数. 匈牙利算法:把行和列看做两个集合,当有障碍物连接时连一条边,问题转换为最小点覆盖数==二分图最大匹配数 趣味入门:http:// ...

  9. 51Nod 2006 飞行员配对(二分图最大匹配)-匈牙利算法

    2006 飞行员配对(二分图最大匹配) 题目来源: 网络流24题 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 第二次世界大战时期,英国皇家空军从沦陷国 ...

随机推荐

  1. Python之python简介

    一.Python的优缺点 优点: 1.Python的定位是“优雅”.“明确”.“简单”,所以Python程序看上去总是简单易懂,初学者学Python,不但入门容易,而且将来深入下去,可以编写那些非常非 ...

  2. div设置百分比高度 宽度

    给div按百分比设置高度 宽度两种方法: 第一种是给body标签设置他的高度值,xxxpx,div就会根据body的像素值取百分比: 第二种方法就是在div属性中加入 position:absolut ...

  3. mac 配置apache

    Apache配置 对httpd.conf文件的配置.首先打开 /etc/apache2/httpd.conf文件,也就是Apache2.4的相关配置文件. 连接php 首先我们将相应的PHP版本配置进 ...

  4. 只要你用atom修改后保存代码文件的时候,你在chrome上的页面就会自动刷新。

    学习html和css的时候Ctrl+s 以后预览网页需要手动刷新 现在不用了 给chrome安装安装LivePage这个插件. 只要你用atom修改后保存代码文件的时候,你在chrome上的页面就会自 ...

  5. EBR-TLV数据格式

    EMV规范中的BER-TLV数据格式:BER-TLV结构由Tag.Length.Value三部分组成. [TAG域]TAG可以由1个与多个字节组成,TAG域的第一个字节编码格式如下: 其中由三部分组成 ...

  6. mybatis映射文件祥解(StudentMapper.xml)

    1)以下是StudentMapper.xml文件,提倡放在与实体同目录下,文件名任意 <?xml version="1.0" encoding="UTF-8&quo ...

  7. weight权重的属性

    权重是把屏幕剩余空间按比例分配 控件使用0dp,则实际的宽度比就等于权重比 控件wrap_content,那么权重越大,位置占的越多,再小不过wrap_content 控件match_parent,那 ...

  8. flutter 常用plugins

    搜索plugins flutter plugins搜索地址 谷歌官方plugins https://pub.dev/packages?q=http 到这个链接里面去搜索 https://github. ...

  9. C++之ListNode

    单链表,弄清楚可stl中list的区别 ListNode的结构 struct ListNode { int val; //当前结点的值 ListNode *next; //指向下一个结点的指针 Lis ...

  10. Pytorch-tensor的维度变化

    引言 本篇介绍tensor的维度变化. 维度变化改变的是数据的理解方式! view/reshape:大小不变的条件下,转变shape squeeze/unsqueeze:减少/增加维度 transpo ...