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 难度:基础题 收藏 关注 第二次世界大战时期,英国皇家空军从沦陷国 ...
随机推荐
- redis,memcached,mongodb之间的区别
Redis Redis的优点: 支持多种数据结构,如 string(字符串). list(双向链表).dict(hash表).set(集合).zset(排序set).hyperloglog(基数估算) ...
- CF258B
CF258B 题意: 7个人在 $ [1,m] $ 区间内取数,求第一个人选的数的4和7的个数大于其他人的4和7个数总和的方案数. 解法: 要求输入的 $ m $ 可以很大,而且需要按位考虑每隔人的贡 ...
- [CSP-S模拟测试]:C(倍增+数学)
题目传送门(内部题152) 输入格式 第一行两个整数$N,Q$. 接下来一行$N$个整数,第$i$个为$a_i$. 接下来的$N-1$行,每行两个整数$u,v$.表示$u,v$之间有一条边. 接下来的 ...
- 【软件工程】Beta冲刺(1/5)
链接部分 队名:女生都队 组长博客: 博客链接 作业博客:博客链接 小组内容 恩泽(组长) 过去两天完成了哪些任务 描述 tomcat的学习与实现 服务器后端部署,API接口的beta版实现 后端代码 ...
- decimal模块 --数字的精度、保留小数位数、取整问题
开始之前需要注意一点是:精度值为数字的总位数,如:1.23, 精度值为3: 0.123,精度值也为3 1.更改默认精度值后,直接进行计算即可保留对应精度值 from decimal import ge ...
- JDBC与ODBC
ODBC(Open Database Connectivity)是一组对数据库访问的标准API,这些API通过SQL来完成大部分任务,而且它本身也支持SQL语言,支持用户发来的SQL.ODBC定义了 ...
- 【log4j】log4j.properties 文件示例
# 下面的文件内容是写程序长期要用的,放在这里留个底#Output information(higher than INFO) to stdout and file.info/debug/error ...
- 用PHP自带函数对二维数组进行排序
经常会面临这样的需求,虽然有时候我们可以在数据库查询的时候,直接对数据进行排序,但还是无法满足日益复杂的业务需求. 这里边会用到两个函数 一个是array_column()函数,这个函数接受三个参数. ...
- Spring事务注解分析
1.使用spring事务注解 2.手写事务注解 1).sql执行器 2).事务注解定义 3).AOP实现事务具体实现(同一个线程中使用同一个连接) 4).应用使用注解前 5).应用使用注解后
- LC 869. Reordered Power of 2
Starting with a positive integer N, we reorder the digits in any order (including the original order ...