Fire Net(HDU-1045)(匈牙利最大匹配)(建图方式)
题意
有一个 n*n 的图,. 代表空白区域,X 代表墙,现在要在空白区域放置结点,要求同一行同一列只能放一个,除非有墙阻隔,问最多能放多少个点
思路
只有在墙的阻隔情况下,才会出现一行/列出现多个点的情况,那么可以考虑进行缩点,将同一行且没有墙体阻隔的区域缩成一个点,放到左点集中,将同一列且没有墙体阻隔的区域缩成一个点,放到右点集中,从而建成一个二分图
假设 i 为行编号,j 为列编号,若 i-j 之间存在一条边,就相当于在方格 (i,j) 上放了一个点,这个假设使得在没有墙体阻隔的情况下,i 行 j 列不能再放其他的点,那么在不考虑 不能同行同列 的情况下,将所有边连接起来,即行列缩点后,对应方格编号连边
建好图后,在图上求最大匹配即可
C++代码一
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define PI acos(-1.0)
#define E 1e-9
#define INF 0x3f3f3f3f
#define LL long long
const int MOD=1E9+;
const int N=+;
const int dx[]={-,,,};
const int dy[]={,,-,};
using namespace std;
int n;//n行n列
bool vis[N];//vis[i]表示是否在交替路中
int link[N];//存储连接点
int G[N][N];//存边
char str[N][N];
int x[N][N],cntX;//行点集
int y[N][N],cntY;//列点集
bool dfs(int x){
for(int y=;y<cntY;y++){//对x的每个邻接点
if(G[x][y]==&&!vis[y]){//不在交替路中
vis[y]=true;//放入交替路
if(link[y]==- || dfs(link[y])){//如果是未匹配点,说明交替路是增广路
link[y]=x;//交换路径
return true;//返回成功
}
}
}
return false;//不存在增广路,返回失败
}
int hungarian(){
int ans=;//记录最大匹配数
memset(link,-,sizeof(link));
for(int i=;i<cntX;i++){//从左侧开始每个结点找一次增广路
memset(vis,false,sizeof(vis));
if(dfs(i))//找到一条增广路,形成一个新匹配
ans++;
}
return ans;
}
int main(){ while(scanf("%d",&n)!=EOF&&n){
memset(x,,sizeof(x));
memset(y,,sizeof(y));
memset(G,false,sizeof(G)); for(int i=;i<n;i++)
scanf("%s",str[i]); //对行缩点
cntX=;
for(int i=;i<n;i++){//第i行
for(int j=;j<n;j++){//第j列
if(str[i][j]=='.')//同一区域
x[i][j]=cntX;
if(str[i][j]=='X')//墙体阻隔
cntX++;
}
cntX++;//下一行
} //对列缩点
cntY=;
for(int j=;j<n;j++){//第j列
for(int i=;i<n;i++){//第i行
if(str[i][j]=='.')//同一区域
y[i][j]=cntY;
if(str[i][j]=='X')//墙体阻隔
cntY++;
}
cntY++;//下一列
} //连边
for(int i=;i<n;i++)
for(int j=;j<n;j++)
if(str[i][j]=='.')
G[x[i][j]][y[i][j]]=true; printf("%d\n",hungarian());
}
return ;
}
C++代码二
#include <bits/stdc++.h>
using namespace std;
int n;
struct node
{
int a = , b = ;
};
node id[][];
char mp[][];
bool link[][];
bool vis[];
int use[];
int hcnt,rcnt; void dfsh(int x,int y){
if(y <= n && mp[x][y] == '.'){
id[x][y].a = hcnt;
dfsh(x,y+);
}
} void dfsr(int x,int y){
if(x <= n && mp[x][y] == '.'){
id[x][y].b = rcnt;
dfsr(x+,y);
}
} int find(int x)
{
for (int s = ; s < rcnt; s++) {
if (link[x][s] && !vis[s]) {
vis[s] = ;
if (use[s] == || find(use[s])) {
use[s] = x;
return ;
}
}
}
return ;
} int main(int argc, char const *argv[])
{
while(cin >> n && n){
for(int i = ;i <= n ;i ++){
cin >> mp[i] + ;
} memset(id,,sizeof id);
memset(link,,sizeof link);
memset(use,,sizeof use);
hcnt = rcnt = ;
for(int i = ;i <= n;i ++){
for(int j = ;j <= n ;j ++){
if(mp[i][j] == 'X'){
continue;
}
if(id[i][j].a == ){
dfsh(i,j);
hcnt ++;
}
if(id[i][j].b == ){
dfsr(i,j);
rcnt ++;
}
link[id[i][j].a][id[i][j].b] = ;
}
}
int sum = ;
for(int i = ;i < hcnt;i ++){
memset(vis,,sizeof vis);
if(find(i)) sum ++;
}
printf("%d\n",sum );
} return ;
}
C++代码三
#define N 6
#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char k[N][N];
int book[N][N];
int n,ma;
void dfs(int step)
{
if(step>ma)//保留每次能放得最大碉堡数
{
ma=step;
return;
}
for(int i=; i<n; i++)
{
for(int j=; j<n; j++)
{
if(k[i][j]=='.'&&!book[i][j])//如果这个位置可以放碉堡
{
int a=i,b=i,c=j,d=j;
//向四个方向覆盖,遇到边界或墙停止
while(a>=&&k[a][j]=='.'){book[a][j]++;a--;}
while(b<n&&k[b][j]=='.'){book[b][j]++;b++;}
while(c>=&&k[i][c]=='.'){book[i][c]++;c--;}
while(d<n&&k[i][d]=='.'){book[i][d]++;d++;}
dfs(step+);//放置的碉堡数加1
a=i,b=i,c=j,d=j;
//取消覆盖
while(a>=&&k[a][j]=='.'){book[a][j]--;a--;}
while(b<n&&k[b][j]=='.'){book[b][j]--;b++;}
while(c>=&&k[i][c]=='.'){book[i][c]--;c--;}
while(d<n&&k[i][d]=='.'){book[i][d]--;d++;}
}
}
}
return;
}
int main()
{
while(scanf("%d",&n)&&n)
{
for(int i=; i<n; i++)
scanf("%s",k[i]);
memset(book,,sizeof(book));
ma=;
dfs();
printf("%d\n",ma);
}
return ;
}
DFS
Fire Net(HDU-1045)(匈牙利最大匹配)(建图方式)的更多相关文章
- Fire Net HDU - 1045 (二分图匹配)
题意: 给出一张图,图中'X'表示wall,'.'表示空地,可以放置blockhouse同一条直线上只能有一个blockhouse,除非有wall 隔开,问在给出的图中最多能放置多少个blockhou ...
- Eliminate the Conflict HDU - 4115(2-sat 建图 hhh)
题意: 石头剪刀布 分别为1.2.3,有n轮,给出了小A这n轮出什么,然后m行,每行三个数a b k,如果k为0 表示小B必须在第a轮和第b轮的策略一样,如果k为1 表示小B在第a轮和第b轮的策略不一 ...
- Meeting HDU - 5521 虚点建图
Problem Description Bessie and her friend Elsie decide to have a meeting. However, after Farmer John ...
- HDU 4292 Food (建图思维 + 最大流)
(点击此处查看原题) 题目分析 题意:某个餐馆出售f种食物,d种饮料,其中,第i种食物有fi份,第i种饮料有di份:此时有n个人来餐馆吃饭,这n个人必须有一份食物和一份饮料才会留下来吃饭,否则,他将离 ...
- 逃生 HDU 4857(反向建图 + 拓扑排序)
逃生 链接 Problem Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必 ...
- 神奇的建图方式(Tarjan)——小z玩游戏
原题来自与:洛谷 P5676(GZOI2017) 链接: https://www.luogu.com.cn/problem/P5676 题面: 题意比较明显,如果已经建好了边,那么跑个Tarjan ...
- A - Fire Net - hdu 1045(二分图匹配)
题意:一个阵地可以向四周扫射,求出来最多能修多少个阵地,墙不可以被扫射透,阵地不能同行或者或者列(有墙隔着例外) 分析:很久以前就做过这道题..当时是练习深搜来着,不过时间复杂度比较高,现在再看突然发 ...
- Fire Net HDU - 1045(二分匹配)
把每一列中相邻的 . 缩为一个点 作为二分图的左边 把每一行中相邻的 . 缩为一个点 作为二分图的右边 然后求最大匹配即可 这题用匈牙利足够了...然而..我用了hk...有点大材小用的感觉// ...
- (匹配)Fire Net --hdu --1045
链接: http://acm.hdu.edu.cn/showproblem.php?pid=1045 http://acm.hust.edu.cn/vjudge/contest/view.action ...
随机推荐
- 使用SpringBoot校验客户端传来的数据
前端的数据校验都是辣鸡!后端天下第一! 很多时候我们后端需要前端传数据过来, 比如注册, 修改用户名, 修改密码等等.很可能有些用户就喜欢搞事, 喜欢发一大堆乱七八糟的数据到后端来, 甚至有些前端老哥 ...
- <context:component-scan>标签报错解决方案
- Python轻量级开发工具Genay使用
Genay是一个轻量级的免费,开放源代码的开发工具,支持很多的文件类型,并且支持很多的插件,启动快速.安装包只有十几兆,相关的插件也不大,相比pycharm专业版需要收费,并且社区版的安装包大小有两百 ...
- LC 406. Queue Reconstruction by Height
Suppose you have a random list of people standing in a queue. Each person is described by a pair of ...
- ASimpleCache源码分析
ASimpleCache里只有一个JAVA文件——ACache.java,首先我用思维导图制作了ACache类的详细结构图: 通过分析官方给的demo来驱动源码分析吧 以字符串存储为例(官方给的dem ...
- Tomcat 8.5 配置 SSL 证书
前文: 1.以上内容仅支持Linux-Tomcat配置 正文: 说一下我遇到的坑,我使用的服务器是阿里云服务器,阿里云提供的云服务器Tomcat配置SSL是7.0版本,跟8.5出入较大. 以下为阿里提 ...
- iOS杂记-告警清理
NS_ASSUME_NONNULL_BEGIN @interface Robot : NSObject @property (copy,readonly) NSString *name; - (nul ...
- tomcat启动不了?
tomcat是用Java编写的,首先需要配置好jdk虚拟机, 要安装 JDK,请转至http://www.oracle.com/technetwork/java/javase/downloads/jd ...
- Web测试方法_02
1.页面链接检查 检查每一个链接是否都有对应的页面,页面与页面之间的来回切换是否正常响应,包括一些返回页面的链接是否正常,还要检查点击图片所链接的页面是否准确展示. 2.相关性检查 功能相关性检查:例 ...
- list 属性字段直接转成字符串数组
List<Car> cars = //whatever; string concat = String.Join(",", cars.Select(c => c. ...