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. Gradle build-info.xml not found for module app.Please make sure that you are using gradle plugin '2.0.0-alpha4' or higher.

    解决方法:去掉“Enable Instant run to host swap code/resource changes on deploy(default enabled)”的勾选项 Settin ...

  2. hdu-2647 Reward && hdu-2049产生冠军 &&hdu-3342Legal or Not(拓扑排序)

    题目链接: hdu-2647 /*Problem : 2647 ( Reward ) Judge Status : Accepted RunId : 16919085 Language : G++ A ...

  3. hdu-5665 Lucky(水题)

    题目链接: Lucky Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Others) Pro ...

  4. python multiprocessing多进程应用

    multiprocessing包是Python中的多进程管理包,可以利用multiprocessing.Process对象来创建进程,Process对象拥有is_alive().join([timeo ...

  5. July Cook-Off 2017

    Chang and Bitwise OR 分析:因为按位或最后肯定小于等于加,所以把所有数按位或即可 #include "iostream" #include "cstd ...

  6. 《The challenge of realistic music generation: modelling raw audio at scale》论文阅读笔记

    The challenge of realistic music generation: modelling raw audio at scale 作者:Deep  mind三位大神 出处:NIPS ...

  7. bzoj1095

    动态点分治 先建出点分树,每个点上维护两个堆,s1,s2,分别表示子树中到点分树中父亲的所有长度,每个儿子s1的最大值,那么对于每个点答案就是s2的最大+次大,再维护一个s3保存这个. 首先我们要搞一 ...

  8. keystone nova v2 python

  9. CF-805D

    D. Minimum number of steps time limit per test 1 second memory limit per test 256 megabytes input st ...

  10. 5、overflow、hover

    一.overflow 1.属性介绍 说明: 这个属性定义溢出元素内容区的内容会如何处理.如果值为 scroll,不论是否需要,用户代理都会提供一种滚动机制.因此,有可能即使元素框中可以放下所有内容也会 ...