POJ3020 匹配
题目大意:给定一地图,*可以和相邻的*匹配成一对儿,问最少需要对儿匹配才能使所有*都被匹配到。
很直白的最小点覆盖,即ans = 点集数-最大匹配数。
不过一开始要对图进行遍历得到点集,找到一个*就把点集数+1,并和周围的匹配即可。为了防止重复,
我只匹配了左边和上边的点。由于用邻接表保存了双向路,所以最后匹配结果会是最大匹配的二倍。
数据范围是40*10,匈牙利即可,因此不用Karp进行优化。
附AC代码:
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
#define oo 0x3f3f3f3f
char maps[][];
int nums[][];
struct ad
{
int next, to;
} edge[];
int head[], edge_num, used[], vis[];
void Add(int x, int y)
{
edge[edge_num].next = head[x];
edge[edge_num].to = y;
head[x] = edge_num++;
}
bool Hungary(int u)
{
for(int i=head[u]; i!=-; i=edge[i].next)
{
int To = edge[i].to;
if(!vis[To])
{
vis[To] = ;
if(!used[To] || Hungary(used[To]))
{
used[To] = u;
return true;
}
} }
return false;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int m, n;
scanf("%d %d", &m, &n);
for(int i=; i<m; i++)
scanf("%s", maps[i]);
int cnt = ;
memset(head, -, sizeof(head));
edge_num = ;
for(int i=; i<m; i++)
for(int j=; j<n; j++)
{
if(maps[i][j]=='*')
{
cnt++;
nums[i][j] = cnt;
if(i>= && maps[i-][j]=='*')
{
Add(nums[i-][j], nums[i][j]);
Add(nums[i][j], nums[i-][j]);
}
if(j>= && maps[i][j-]=='*')
{
Add(nums[i][j], nums[i][j-]);
Add(nums[i][j-], nums[i][j]);
}
}
}
memset(used, , sizeof(used));
int ans = ;
for(int i=; i<=cnt; i++)
{
memset(vis, , sizeof(vis));
if(Hungary(i))ans++;
}
printf("%d\n", cnt-ans/);
}
return ;
}
Karp算法优化代码:
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
using namespace std;
#define oo 0x3f3f3f3f
const int Maxn = ;
char maps[][];
int nums[][], head[Maxn];
struct ad
{
int to, next;
}edge[Maxn*Maxn];
int depth, depx[Maxn], depy[Maxn], vis[Maxn], usedx[Maxn], usedy[Maxn], edge_num;
void Add(int x, int y)
{
edge[edge_num].to = y;
edge[edge_num].next = head[x];
head[x] = edge_num++;
}
bool bfs(int cnt)
{
memset(depx, -, sizeof(depx));
memset(depy, -, sizeof(depy));
depth = oo;
queue<int>Q;
for(int i=; i<=cnt; i++)
{
if(!usedx[i])
{
depx[i] = ;
Q.push(i);
}
} while(Q.size())
{
int now = Q.front();
Q.pop();
if(depx[now]>depth)return true; for(int i=head[now]; i!=-; i=edge[i].next)
{
int To = edge[i].to;
if(depy[To] == -)
{
depy[To] = depx[now] + ;
if(!usedy[To])
depth = depy[To];
else
{
depx[usedy[To]] = depy[To] + ;
Q.push(usedy[To]);
}
}
}
} if(depth==oo)return false;
return true;
}
bool Hungary(int u)
{
for(int i=head[u]; i!=-; i=edge[i].next)
{
int To = edge[i].to;
if(!vis[To])
{
vis[To] = ;
if(usedy[To] && depy[To]==depth)continue; if(!usedy[To] || Hungary(usedy[To]))
{
usedx[u] = To;
usedy[To] = u;
return true;
}
}
}
return false;
}
int Karp(int cnt)
{
memset(usedx, , sizeof(usedx));
memset(usedy, , sizeof(usedy)); int ans = ; while(bfs(cnt))
{
memset(vis, , sizeof(vis));
for(int i=; i<=cnt; i++)
if(!usedx[i] && Hungary(i))ans++;
}
return ans;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int n, m;
edge_num = ;
scanf("%d %d", &n, &m);
for(int i=; i<n; i++)
scanf("%s", maps[i]);
memset(head, -, sizeof(head));
int cnt = ;
for(int i=; i<n; i++)
for(int j=; j<m; j++)
{
if(maps[i][j]=='*')
{
cnt++;
nums[i][j] = cnt;
if(i->= && maps[i-][j]=='*')
{
Add(nums[i-][j], nums[i][j]);
Add(nums[i][j], nums[i-][j]);
}
if(j->= && maps[i][j-]=='*')
{
Add(nums[i][j], nums[i][j-]);
Add(nums[i][j-], nums[i][j]);
}
}
}
int ans = Karp(cnt);
printf("%d\n", cnt-ans/);
}
return ;
}
POJ3020 匹配的更多相关文章
- POJ-3020 Antenna Placement---二分图匹配&最小路径覆盖&建图
题目链接: https://vjudge.net/problem/POJ-3020 题目大意: 一个n*m的方阵 一个雷达可覆盖两个*,一个*可与四周的一个*被覆盖,一个*可被多个雷达覆盖问至少需要多 ...
- POJ3020:Antenna Placement(二分图匹配)
Antnna Placement Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11093 Accepted: 5459 ...
- POJ3020【二分匹配】
思路: ---说给自己 一开始想的是从1-h*w标记整幅图,建图是星号和 {他,与他相连的星号} 建边,肯定要去匹配"*"啊,所以空格一定不会去造,然后就理解成了最小点覆盖,然而对 ...
- POJ3020 二分图匹配——最小路径覆盖
Description The Global Aerial Research Centre has been allotted the task of building the fifth gener ...
- poj3020二分图匹配
The Global Aerial Research Centre has been allotted the task of building the fifth generation of mob ...
- poj3020 二分图匹配 最大独立集
这是一道水题, 这里是最大流解法,之后再补 坑在又忘了反向建边了 题意:给你二维bool数组,让你求出能用多米诺骨牌覆盖所有 1 且骨牌最少的放法(因为多米诺骨牌1*2的结构方便描述,原题没有),原本 ...
- POJ3020——Antenna Placement(二分图的最大匹配)
Antenna Placement DescriptionThe Global Aerial Research Centre has been allotted the task of buildin ...
- poj3020 Antenna Placement 匈牙利算法求最小覆盖=最大匹配数(自身对应自身情况下要对半) 小圈圈圈点
/** 题目:poj3020 Antenna Placement 链接:http://poj.org/problem?id=3020 题意: 给一个由'*'或者'o'组成的n*m大小的图,你可以用一个 ...
- javascript匹配各种括号书写是否正确
今天在codewars上做了一道题,如下 看上去就是验证三种括号各种嵌套是否正确书写,本来一头雾水,一种括号很容易判断, 但是三种怎么判断! 本人只是个前端菜鸟,,不会什么高深的正则之类的. 于是,在 ...
随机推荐
- :before和 :after
:before和:after的作用就是在指定的元素内容(而不是元素本身)之前或者之后插入一个包含content属性指定内容的行内元素,最基本的用法如下: #example:before { conte ...
- JSTL函数标签库 fn标签
JSTL函数标签库 fn标签 在使用jstl的函数标签库之前需要在页面中引入: <%@ taglib prefix="fn" uri="http://java.su ...
- Struts2从一个action转到另一个action的两种方法
在Struts2中,Action处理完用户请求后,将会返回一个字符串对象,这个字符串对象就是一个逻辑视图名.Struts 2通过配置逻辑视图名和物理视图之间的映射关系,一旦系统收到Action返回的某 ...
- imx6移植ffmpeg2.3
yasm ./configure --enable-shared --prefix=/usr/local/arm/yasm --host=arm-linux 修改Makefile CC=arm-non ...
- 深入探索c++对象模型
第一章关于对象 c++在布局和存取时间的额外负担主要有virtual引起 virtual function:运行期动态绑定 virtual base class :base class多次出现在派生类 ...
- 采用TCP协议实现PIC18F97J60 ethernet bootloader
了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序). TCP/IP Stac ...
- 改变BootStrap主题颜色
摘自:http://www.asp.net/visual-studio/overview/2013/creating-web-projects-in-visual-studio#bootstrap Y ...
- IT界里的生日
MS-DOS 1981年7月27日 windows 3.0 1990年5月22日 windows 3.11 1992年3月18日 Windows 95 1995年8月24日 Windows ...
- 38、重新复习javascript之三
前言 虽然吧,每天都没有什么太有技术性的工作者,但是技术不能丢,希望也要有,人如果没有希望那不就和咸鱼一样了吗?小伙加油吧 1.html与javascript结合 <!DOCTYPE html ...
- [转]配置sonar、jenkins进行持续审查
本文以CentOS操作系统为例介绍Sonar的安装配置,以及如何与Jenkins进行集成,通过pmd-cpd.checkstyle.findbugs等工具对代码进行持续审查. 一.安装配置sonar ...