HDU - 1045 Fire Net (二分图最大匹配-匈牙利算法)
匈牙利算法简介
个人认为这个算法是一种贪心+暴力的算法,对于二分图的两部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 (二分图最大匹配-匈牙利算法)的更多相关文章
- hdu 2063 过山车 (最大匹配 匈牙利算法模板)
匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最 ...
- HDU 1045 - Fire Net - [DFS][二分图最大匹配][匈牙利算法模板][最大流求二分图最大匹配]
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1045 Time Limit: 2000/1000 MS (Java/Others) Mem ...
- UESTC 919 SOUND OF DESTINY --二分图最大匹配+匈牙利算法
二分图最大匹配的匈牙利算法模板题. 由题目易知,需求二分图的最大匹配数,采取匈牙利算法,并采用邻接表来存储边,用邻接矩阵会超时,因为邻接表复杂度O(nm),而邻接矩阵最坏情况下复杂度可达O(n^3). ...
- Ural1109_Conference(二分图最大匹配/匈牙利算法/网络最大流)
解题报告 二分图第一题. 题目描写叙述: 为了參加即将召开的会议,A国派出M位代表,B国派出N位代表,(N,M<=1000) 会议召开前,选出K队代表,每对代表必须一个是A国的,一个是B国的; ...
- HDU1068 (二分图最大匹配匈牙利算法)
Girls and Boys Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- HDU 1045——Fire Net——————【最大匹配、构图、邻接矩阵做法】
Fire Net Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Sta ...
- poj - 3041 Asteroids (二分图最大匹配+匈牙利算法)
http://poj.org/problem?id=3041 在n*n的网格中有K颗小行星,小行星i的位置是(Ri,Ci),现在有一个强有力的武器能够用一发光速将一整行或一整列的小行星轰为灰烬,想要利 ...
- 二分图最大匹配(匈牙利算法) POJ 3041 Asteroids
题目传送门 /* 题意:每次能消灭一行或一列的障碍物,要求最少的次数. 匈牙利算法:把行和列看做两个集合,当有障碍物连接时连一条边,问题转换为最小点覆盖数==二分图最大匹配数 趣味入门:http:// ...
- 51Nod 2006 飞行员配对(二分图最大匹配)-匈牙利算法
2006 飞行员配对(二分图最大匹配) 题目来源: 网络流24题 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 第二次世界大战时期,英国皇家空军从沦陷国 ...
随机推荐
- tqdm如何在pandas里面使用
原文: https://segmentfault.com/a/1190000016059726 当然,首先我们得载入模块,在notebook中使用tqdm带的基于Js显示的进度条前,请务必检查是否安装 ...
- putty ssh 证书登录及问题
1.用PUTTYGEN.exe生成密钥,生成的时候鼠标在进度条下面的空白处移动,为什么?就理解成随机得厉害点吧. 2.保存私钥,请看下面的图片说明 3.把公钥的内容想办法放到用户目录的.ssh/aut ...
- springMVC课程笔记(二)springMVC组件配置
1.springMVC的DispatcherServlet前段控制器配置,如下图所示在web.xml中配置如下内容: 2.在spring配置文件中,配置处理器适配器HandlerAdapter和映射器 ...
- Linux设备驱动程序 之 主次设备号
主设备号和次设备号 对字符设备的访问是通过文件系统内的设备名称进行的,这些名称被称为特殊文件.设备文件.或者简单称之为文件系统树的节点,它们通常位于/dev目录.字符设备驱动程序的设备文件可以通过ls ...
- 【软件工程】Alpha事后诸葛亮
链接部分 队名:女生都队 组长博客: 博客链接 作业博客:博客链接 参考邹欣老师的问题模板进行总结思考 一.设想和目标 1.我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的 ...
- 删除Linux系统多余的引导
问题: 电脑中安装了多个Linux系统,需要删除不用的Linux系统的引导 解决方法: open terminal: su - 切换root用户 cd /boot/ ls ... grub ...
- Linux中soft nproc 、soft nofile和hard nproc以及hard nofile配置
Linux中soft nproc .soft nofile和hard nproc以及hard nofile配置 "soft" 和 "hard" 的区别 soft ...
- 使用 usb 调试的时候,连接上电脑没反应
使用 usb 调试的时候,连接上电脑没反应 原因: 手机上没有信任本计算机的授权,请在手机上信任该授权 解决方法: 原因就是手机上会有一个弹话框,让我们信任该计算机,我们才可以进行 usb调试 我们的 ...
- ora-01578
SQL> exec DBMS_STATS.GATHER_DATABASE_STATS; BEGIN DBMS_STATS.GATHER_DATABASE_STATS; END; * ERROR ...
- PHP批量写入数据、批量删除数据
批量插入可以参考$sql = "insert into data (id,ip,data) values ";for($i=0;$i<100;$i++){$sqls[]=& ...