http://poj.org/problem?id=3020

首先注意到,答案的最大值是'*'的个数,也就是相当于我每用一次那个技能,我只套一个'*',是等价的。

所以,每结合一对**,则可以减少一次使用,所以就是找**的最大匹配数目。

对于每一个*,和它的上下左右连接一条边(如果是*才连)

那么,这个图是一个二分图,怎么找到左边集合S,右边集合T呢?

我的做法是染色一次,就可以。

这题应该不能贪心吧。

3 5

*****

o***o

o*o*o

其实也可以不分开S、T

跑一发最大匹配,然后匹配数 / 2即可。意思就是match[1] = 2,也可以match[2] = 1,但是两者是只算一个匹配。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = + ;
char str[maxn][maxn];
int a[maxn][maxn];
struct Node {
int u, v, tonext;
}e[maxn * maxn * ];
int first[maxn * maxn * ], num;
void addEdge(int u, int v) {
++num;
e[num].u = u, e[num].v = v;
e[num].tonext = first[u];
first[u] = num;
}
int match[maxn * maxn * ], book[maxn * maxn * ], DFN;
bool dfs(int u) {
for (int i = first[u]; i; i = e[i].tonext) {
int v = e[i].v;
if (book[v] == DFN) continue;
book[v] = DFN;
if (match[v] == || dfs(match[v])) {
match[v] = u;
return true;
}
}
return false;
}
vector<int>vc;
int hungary() {
memset(match, , sizeof match);
int ans = ;
for (int i = ; i < vc.size(); ++i) {
++DFN;
if (dfs(vc[i])) ans++;
}
return ans;
}
int col[maxn * maxn * ];
void ran(int cur, int which) {
col[cur] = which;
book[cur] = DFN;
for (int i = first[cur]; i; i = e[i].tonext) {
int v = e[i].v;
if (book[v] == DFN) continue;
ran(v, !which);
}
}
void work() {
memset(first, , sizeof first);
num = ;
int to = ;
int n, m;
cin >> n >> m;
for (int i = ; i <= n; ++i) {
scanf("%s", str[i] + );
}
memset(a, , sizeof a);
for (int i = ; i <= n; ++i) {
for (int j = ; j <= m; ++j) {
if (str[i][j] == '*') {
a[i][j] = ++to;
}
}
}
for (int i = ; i <= n; ++i) {
for (int j = ; j <= m; ++j) {
if (a[i][j + ]) addEdge(a[i][j], a[i][j + ]);
if (a[i + ][j]) addEdge(a[i][j], a[i + ][j]);
if (a[i][j - ]) addEdge(a[i][j], a[i][j - ]);
if (a[i - ][j]) addEdge(a[i][j], a[i - ][j]);
}
}
memset(col, -, sizeof col);
++DFN;
for (int i = ; i <= to; ++i) {
if (book[i] != DFN) ran(i, );
}
vc.clear();
for (int i = ; i <= to; ++i) {
if (col[i] == ) vc.push_back(i);
}
cout << to - hungary() << endl;
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
int t;
cin >> t;
while (t--) work();
return ;
}

POJ - 3020  Antenna Placement 二分图最大匹配的更多相关文章

  1. [POJ] 3020 Antenna Placement(二分图最大匹配)

    题目地址:http://poj.org/problem?id=3020 输入一个字符矩阵,'*'可行,'o'不可行.因为一个点可以和上下左右四个方向的一个可行点组成一个集合,所以对图进行黑白染色(每个 ...

  2. POJ 3020 Antenna Placement(二分图 匈牙利算法)

    题目网址:  http://poj.org/problem?id=3020 题意: 用椭圆形去覆盖给出所有环(即图上的小圆点),有两种类型的椭圆形,左右朝向和上下朝向的,一个椭圆形最多可以覆盖相邻的两 ...

  3. POJ 3020 Antenna Placement (二分图最小路径覆盖)

    <题目链接> 题目大意:一个矩形中,有N个城市’*’,现在这n个城市都要覆盖无线,每放置一个基站,至多可以覆盖相邻的两个城市.问至少放置多少个基站才能使得所有的城市都覆盖无线? 解题分析: ...

  4. 二分图最大匹配(匈牙利算法) POJ 3020 Antenna Placement

    题目传送门 /* 题意:*的点占据后能顺带占据四个方向的一个*,问最少要占据多少个 匈牙利算法:按坐标奇偶性把*分为两个集合,那么除了匹配的其中一方是顺带占据外,其他都要占据 */ #include ...

  5. poj 3020 Antenna Placement(最小路径覆盖 + 构图)

    http://poj.org/problem?id=3020 Antenna Placement Time Limit: 1000MS   Memory Limit: 65536K Total Sub ...

  6. POJ 3020 Antenna Placement 【最小边覆盖】

    传送门:http://poj.org/problem?id=3020 Antenna Placement Time Limit: 1000MS   Memory Limit: 65536K Total ...

  7. POJ 3020 Antenna Placement 最大匹配

    Antenna Placement Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6445   Accepted: 3182 ...

  8. POJ 3020 Antenna Placement【二分匹配——最小路径覆盖】

    链接: http://poj.org/problem?id=3020 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22010#probl ...

  9. poj 3020 Antenna Placement (最小路径覆盖)

    链接:poj 3020 题意:一个矩形中,有n个城市'*'.'o'表示空地,如今这n个城市都要覆盖无线,若放置一个基站, 那么它至多能够覆盖本身和相邻的一个城市,求至少放置多少个基站才干使得全部的城市 ...

随机推荐

  1. Android studio 添加assets文件夹

    我们知道Eclipse创建的工程默认是有个assets文件夹的,但是Android studio默认没有帮我们创建,那么我们就自己创建一个就好啦. (1)手动创建 在项目的顶部有个下拉,默认选择的是A ...

  2. 页面渲染——简化paint复杂程度和区域

    Paint是填充像素并且最后合成在用户的屏幕上的过程. 通常是在管道中耗费最大的,你要尽可能的避免使用paint. 动画中使用除了transform和opacity的动画属性都将触发paint pai ...

  3. 加快你的JavaScript加载时间

    发现可以提速的内容 你必须首先发现你的什么图片和HTML加载缓慢了你的脚本速度,下面提供了方法: 1.  Firefox web-developer toolbar 2.  Firebug Plugi ...

  4. plsql导入cvs 时提示missing right parenthesis

    删除自动生成的时间格式值,如:SQL function框里自动生成的值

  5. Android设备管理器 DevicePolicyManager

    设备管理器有个特点,你注册了之后如果不解除注册就会难以卸载带有设备管理器的应用,目前4.3版本仍未提示用户如何卸载,maybe later. 在「设定-安全」你可以看见「设备管理器」,它提供一些高级功 ...

  6. CodeForces526F:Pudding Monsters (分治)

    In this problem you will meet the simplified model of game Pudding Monsters. An important process in ...

  7. springMVC之HttpServletRequest的getParameterMap()

    request.getParameterMap()的返回类型是Map类型的对象,也就是符合key-value的对应关系,但这里要注意的是,value的类型是String[],而不是String. 得到 ...

  8. [SPOJ1557] Can you answer these queries II

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2482 [算法] 线段树维护历史最值 时间复杂度 : O(NlogN) [代码] #i ...

  9. Ubuntu16.04 安装cuda9.0 cudnn 7.0.5

    参考网址:https://blog.csdn.net/zhuangwu116/article/details/81063234 (1)下载安装文件: 下载cuda9.0 runfile 文件 下载地址 ...

  10. MSD3393/MSD3463 屏参及REG对照表

    概述:TIMMING组成 MOD: BANK:0x1032 VOP: SC_BK10 注意BANK对应: VOP: SC_BK10 例如:MS_U16 m_wPanelHTotal;   Sub VO ...