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上做了一道题,如下 看上去就是验证三种括号各种嵌套是否正确书写,本来一头雾水,一种括号很容易判断, 但是三种怎么判断! 本人只是个前端菜鸟,,不会什么高深的正则之类的. 于是,在 ...
随机推荐
- MySql绿色版下载,安装,配置详解
下载完成之后解压,楼主用的版本是:mysql-5.7.15-winx64 解压完在根目录下建立一个data文件夹和my-default.ini my-default.ini里面的内容如下:(红色内容根 ...
- tomcat出现的PermGen Space问题
java.lang.OutOfmemoryError: PermGen Space 的错误,导致项目无法正常运行. 出现这个错误的原因,总结一下: PermGen Space指的是内存的永久保存区,该 ...
- 二模14day1解题报告
注:Index数☞由4,7组成的十进制数. T1.全排列(permutation) 求n个数的第k个排列中,有多少个Index位置上是Index数. 由于k的范围比较小,n的范围比较大(都是109), ...
- WEBPACK开始
这是一个非常简单的例子,通过这个例子你将学习到 1.How to install webpack 2.How to use webpack 3.How to use loaders 4.How to ...
- 两千行PHP学习笔记
亲们,如约而至的PHP笔记来啦~绝对干货! 以下为我以前学PHP时做的笔记,时不时的也会添加一些基础知识点进去,有时还翻出来查查. MySQL笔记:一千行MySQL学习笔记http://www.cnb ...
- Windows Azure初体验
目前在IT界,云这个概念的第一意思不再是词典里的解释了.不过它们还是有相同点的——也许确实会酝酿出一块大蛋糕,可也是飘在天上,众神分食之,与我等P民无关.所谓云,不过是网络时代发展到一定阶段的必然产物 ...
- 在MFC中使用GDI+的一般方法,以VC6.0编译器为例
1.载解压GDI+开发包: 2.正确设置include & lib 目录: 设置如下:VC6.0编译器菜单Tools->Options->Directories中添加inlude ...
- cs11_c++_lab7
wcount.cc #include <iostream> #include <map> #include <string> #include <algori ...
- C语言PIC32 serial bootloader和C#语言bootloader PC端串口通信程序
了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序). 今天介绍下我新完成的为 ...
- 采集的GPS数据如何正确显示在arcgis和cad中
利用GPS定位卫星,在全球范围内实时进行定位.导航的系统,称为全球卫星定位系统,简称GPS.GPS是由美国国防部研制建立的一种具有全方位.全天候.全时段.高精度的卫星导航系统,能为全球用户提供低成本. ...