POJ - 3020 Antenna Placement 二分图最大匹配
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 二分图最大匹配的更多相关文章
- [POJ] 3020 Antenna Placement(二分图最大匹配)
题目地址:http://poj.org/problem?id=3020 输入一个字符矩阵,'*'可行,'o'不可行.因为一个点可以和上下左右四个方向的一个可行点组成一个集合,所以对图进行黑白染色(每个 ...
- POJ 3020 Antenna Placement(二分图 匈牙利算法)
题目网址: http://poj.org/problem?id=3020 题意: 用椭圆形去覆盖给出所有环(即图上的小圆点),有两种类型的椭圆形,左右朝向和上下朝向的,一个椭圆形最多可以覆盖相邻的两 ...
- POJ 3020 Antenna Placement (二分图最小路径覆盖)
<题目链接> 题目大意:一个矩形中,有N个城市’*’,现在这n个城市都要覆盖无线,每放置一个基站,至多可以覆盖相邻的两个城市.问至少放置多少个基站才能使得所有的城市都覆盖无线? 解题分析: ...
- 二分图最大匹配(匈牙利算法) POJ 3020 Antenna Placement
题目传送门 /* 题意:*的点占据后能顺带占据四个方向的一个*,问最少要占据多少个 匈牙利算法:按坐标奇偶性把*分为两个集合,那么除了匹配的其中一方是顺带占据外,其他都要占据 */ #include ...
- poj 3020 Antenna Placement(最小路径覆盖 + 构图)
http://poj.org/problem?id=3020 Antenna Placement Time Limit: 1000MS Memory Limit: 65536K Total Sub ...
- POJ 3020 Antenna Placement 【最小边覆盖】
传送门:http://poj.org/problem?id=3020 Antenna Placement Time Limit: 1000MS Memory Limit: 65536K Total ...
- POJ 3020 Antenna Placement 最大匹配
Antenna Placement Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6445 Accepted: 3182 ...
- POJ 3020 Antenna Placement【二分匹配——最小路径覆盖】
链接: http://poj.org/problem?id=3020 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22010#probl ...
- poj 3020 Antenna Placement (最小路径覆盖)
链接:poj 3020 题意:一个矩形中,有n个城市'*'.'o'表示空地,如今这n个城市都要覆盖无线,若放置一个基站, 那么它至多能够覆盖本身和相邻的一个城市,求至少放置多少个基站才干使得全部的城市 ...
随机推荐
- Android应用资源---动画资源(Animation Resources)
有两种类型的动画资源: 属性动画 在设定的时间内,通过修改与Animator类相关的对象的属性值来创建一个动画. 视图动画 有两种类型的视图动画框架 补间动画(Tween animation):通过执 ...
- Java版本更新历史(ing)
历史版本特性 JDK Version 1.0 开发代号为Oak(橡树),于1996-01-23发行. JDK Version 1.1 于1997-02-19发行. 引入的新特性包括: 引入JDBC(J ...
- 浅谈如何删除JSP编译后的空行
当你在客户端用view source看JSP生成的代码时,会发现有很多空行,他们是由< %...% >后的回车换行而生成的,也就是说每一行由< %...% >包含的JSP代码到 ...
- php排序方法之插入排序
//插入排序法 $arr = array(3,55,45,2,67,76,6.7,-65,85,4); function insertSort($arr){ for ( $i=0; $i<cou ...
- nginx开发_字符串操作函数
由于ngx_str_t为非NULL结尾的函数,且网络请求中有大量忽略大小写的需求,所以nginx内部封装了许多字符串操作相关的函数,函数名称极其相识,且使用时有有些约定,特此整理. 赋值&拷贝 ...
- 「USACO16OPEN」「LuoguP3147」262144(区间dp
P3147 [USACO16OPEN]262144 题目描述 Bessie likes downloading games to play on her cell phone, even though ...
- GitHub的使用方法
版本控制系统 > Git 分布式 > Subversion 集中式 1. 安装git: # apt-get install git //root权限 $ sudo apt-get inst ...
- Java原子属性更新器AtomicReferenceFieldUpdater的使用
AtomicReferenceFieldUpdater是基于反射的工具类,用来将指定类型的指定的volatile引用字段进行原子更新,对应的原子引用字段不能是private的.通常一个类volatil ...
- VMware桥接模式选择宿主机物理网卡
当宿主机有多块物理网卡时,VMware桥接模式也要根据情况选择使用的物理网卡. 比如宿主机有两块物理网卡,一个连外网,一个连内网,如果想与内网组成局域网就需要选择宿主机的内网网卡,反之选择外网网卡,当 ...
- CF-807B
B. T-Shirt Hunt time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...