题目大意:给定一地图,*可以和相邻的*匹配成一对儿,问最少需要对儿匹配才能使所有*都被匹配到。

很直白的最小点覆盖,即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 匹配的更多相关文章

  1. POJ-3020 Antenna Placement---二分图匹配&最小路径覆盖&建图

    题目链接: https://vjudge.net/problem/POJ-3020 题目大意: 一个n*m的方阵 一个雷达可覆盖两个*,一个*可与四周的一个*被覆盖,一个*可被多个雷达覆盖问至少需要多 ...

  2. POJ3020:Antenna Placement(二分图匹配)

    Antnna Placement Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11093   Accepted: 5459 ...

  3. POJ3020【二分匹配】

    思路: ---说给自己 一开始想的是从1-h*w标记整幅图,建图是星号和 {他,与他相连的星号} 建边,肯定要去匹配"*"啊,所以空格一定不会去造,然后就理解成了最小点覆盖,然而对 ...

  4. POJ3020 二分图匹配——最小路径覆盖

    Description The Global Aerial Research Centre has been allotted the task of building the fifth gener ...

  5. poj3020二分图匹配

    The Global Aerial Research Centre has been allotted the task of building the fifth generation of mob ...

  6. poj3020 二分图匹配 最大独立集

    这是一道水题, 这里是最大流解法,之后再补 坑在又忘了反向建边了 题意:给你二维bool数组,让你求出能用多米诺骨牌覆盖所有 1 且骨牌最少的放法(因为多米诺骨牌1*2的结构方便描述,原题没有),原本 ...

  7. POJ3020——Antenna Placement(二分图的最大匹配)

    Antenna Placement DescriptionThe Global Aerial Research Centre has been allotted the task of buildin ...

  8. poj3020 Antenna Placement 匈牙利算法求最小覆盖=最大匹配数(自身对应自身情况下要对半) 小圈圈圈点

    /** 题目:poj3020 Antenna Placement 链接:http://poj.org/problem?id=3020 题意: 给一个由'*'或者'o'组成的n*m大小的图,你可以用一个 ...

  9. javascript匹配各种括号书写是否正确

    今天在codewars上做了一道题,如下 看上去就是验证三种括号各种嵌套是否正确书写,本来一头雾水,一种括号很容易判断, 但是三种怎么判断! 本人只是个前端菜鸟,,不会什么高深的正则之类的. 于是,在 ...

随机推荐

  1. ant批量执行Jmeter脚本

    JDK,Jmeter默认已经装了 ANT下载:http://ant.apache.org/bindownload.cgi ant环境变量需要配置 ant_home,你解压之后的地址 然后PATH环境变 ...

  2. DMA控制

    1.S3C6410中DMA操作步骤 S3C6410中DMA操作步骤:1.决定使用安全DMAC(SDMAC)还是通用DMAC(DMAC):2.开始相应DMAC的系统时钟,并关闭另外一组的时钟(系统默认开 ...

  3. 新手上路,配置阿里云CentOS服务器LAMP

    最近出了个9.9包月的阿里云一直想弄就买了个半年的,脑子一热选了个CentOS系统的然后就是无尽的代码...... 话不多说直接上步骤:  在实例中选择"连接管理终端",输入一些应 ...

  4. [转]在 ASP.NET MVC 4 中创建为移动设备优化的视图

    原文链接 https://msdn.microsoft.com/zh-cn/magazine/dn296507.aspx 如果深入探讨有关编写移动设备网站的常识性考虑因素,会发现其中有一种内在矛盾.  ...

  5. Upload files to aliyunOSS with bootstrap-fileinput

    本文主要涉及两个概念: 阿里云OSS:对象存储(Object Storage Service,简称OSS),是阿里云对外提供的海量.安全和高可靠的云存储服务. bootstrap-fileinput: ...

  6. CPU阿甘:函数调用的秘密

    个人感言:真正的知识是深入浅出的,码农翻身" 公共号将苦涩难懂的计算机知识,用形象有趣的生活中实例呈现给我们,让我们更好地理解.感谢"码农翻身" 公共号,感谢你们的成果, ...

  7. MVC中的@符号

    1: @if (@Model.DepositList != null) { } 2: @if (@Model.DepositList != null) { foreach (Deposit_ViewM ...

  8. 查看python api

    以下方法可以查看python 的api,包括selenium webdriver,requests等 1.cmd进入dos命令行窗口,输入python -m pydoc -p 2345   (2345 ...

  9. 读取excel数据,并进行统计输出

    package cn.cnnic.ops; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFou ...

  10. python读取excel数据,并可视化展现

    #-*- coding: utf-8 -*- import pandas as pda import matplotlib.pyplot as pyl import matplotlib.font_m ...