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

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

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

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

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

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

这题应该不能贪心吧。

3 5

*****

o***o

o*o*o

其实也可以不分开S、T

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

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <algorithm>
  6. #include <assert.h>
  7. #define IOS ios::sync_with_stdio(false)
  8. using namespace std;
  9. #define inf (0x3f3f3f3f)
  10. typedef long long int LL;
  11.  
  12. #include <iostream>
  13. #include <sstream>
  14. #include <vector>
  15. #include <set>
  16. #include <map>
  17. #include <queue>
  18. #include <string>
  19. #include <bitset>
  20. const int maxn = + ;
  21. char str[maxn][maxn];
  22. int a[maxn][maxn];
  23. struct Node {
  24. int u, v, tonext;
  25. }e[maxn * maxn * ];
  26. int first[maxn * maxn * ], num;
  27. void addEdge(int u, int v) {
  28. ++num;
  29. e[num].u = u, e[num].v = v;
  30. e[num].tonext = first[u];
  31. first[u] = num;
  32. }
  33. int match[maxn * maxn * ], book[maxn * maxn * ], DFN;
  34. bool dfs(int u) {
  35. for (int i = first[u]; i; i = e[i].tonext) {
  36. int v = e[i].v;
  37. if (book[v] == DFN) continue;
  38. book[v] = DFN;
  39. if (match[v] == || dfs(match[v])) {
  40. match[v] = u;
  41. return true;
  42. }
  43. }
  44. return false;
  45. }
  46. vector<int>vc;
  47. int hungary() {
  48. memset(match, , sizeof match);
  49. int ans = ;
  50. for (int i = ; i < vc.size(); ++i) {
  51. ++DFN;
  52. if (dfs(vc[i])) ans++;
  53. }
  54. return ans;
  55. }
  56. int col[maxn * maxn * ];
  57. void ran(int cur, int which) {
  58. col[cur] = which;
  59. book[cur] = DFN;
  60. for (int i = first[cur]; i; i = e[i].tonext) {
  61. int v = e[i].v;
  62. if (book[v] == DFN) continue;
  63. ran(v, !which);
  64. }
  65. }
  66. void work() {
  67. memset(first, , sizeof first);
  68. num = ;
  69. int to = ;
  70. int n, m;
  71. cin >> n >> m;
  72. for (int i = ; i <= n; ++i) {
  73. scanf("%s", str[i] + );
  74. }
  75. memset(a, , sizeof a);
  76. for (int i = ; i <= n; ++i) {
  77. for (int j = ; j <= m; ++j) {
  78. if (str[i][j] == '*') {
  79. a[i][j] = ++to;
  80. }
  81. }
  82. }
  83. for (int i = ; i <= n; ++i) {
  84. for (int j = ; j <= m; ++j) {
  85. if (a[i][j + ]) addEdge(a[i][j], a[i][j + ]);
  86. if (a[i + ][j]) addEdge(a[i][j], a[i + ][j]);
  87. if (a[i][j - ]) addEdge(a[i][j], a[i][j - ]);
  88. if (a[i - ][j]) addEdge(a[i][j], a[i - ][j]);
  89. }
  90. }
  91. memset(col, -, sizeof col);
  92. ++DFN;
  93. for (int i = ; i <= to; ++i) {
  94. if (book[i] != DFN) ran(i, );
  95. }
  96. vc.clear();
  97. for (int i = ; i <= to; ++i) {
  98. if (col[i] == ) vc.push_back(i);
  99. }
  100. cout << to - hungary() << endl;
  101. }
  102.  
  103. int main() {
  104. #ifdef local
  105. freopen("data.txt", "r", stdin);
  106. // freopen("data.txt", "w", stdout);
  107. #endif
  108. int t;
  109. cin >> t;
  110. while (t--) work();
  111. return ;
  112. }

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. linux命令行快捷键记录

    摘自: http://www.cnblogs.com/webzhangnan/p/3221410.html [移动光标] Ctrl+A 标移到行首.它在多数文本编辑器和 Mozilla 的 URL 字 ...

  2. LoadRunner添加检查点

    见过磕长头的人吗?他们的脸和手都很脏,可是心灵却很干净. ——<可可西里> 1.选择需要设置检查点的内容 有如下“添加客户”功能,添加任务操作完成之后,我希望检查是否添加成功.从图中可以看 ...

  3. linux应用之mysql数据库的安装及配置(centos)

    CentOS下Mysql数据库的安装与配置   如果要在Linux上做j2ee开发,首先得搭建好j2ee的开发环境,包括了jdk.tomcat.eclipse的安装(这个在之前的一篇随笔中已经有详细讲 ...

  4. jquery跨域3

    这两天用 Jquery 跨域取数据的时候,经常碰到 invalid label 这个错误,十分的郁闷,老是取不到服务器端发送回来的 json 值, 一般跨域用到的两个方法为:$.ajax 和$.get ...

  5. 动态规划专题 多阶段决策问题 蓝桥杯 K好数

    问题描述 如果一个自然数N的K进制表示中任意的相邻的两位都不是相邻的数字,那么我们就说这个数是K好数.求L位K进制数中K好数的数目.例如K = 4,L = 2的时候,所有K好数为11.13.20.22 ...

  6. 六、mysql语法

    1.条件查询 条件查询需要用到where语句,where必须放到from语句表的后面 执行顺序:先from后where过滤后再检索出来 2.数据排序,asc(升序),desc(降序)默认情况下是asc ...

  7. Laravel框架之Response操作

    public function response(){ //响应json /*$data = [ 'errCode'=>0, 'errMsg' =>'success', 'data' =& ...

  8. PHP实用小程序(四)

    <HTML> <HEAD> <TITLE>访问文件时间属性</TITLE> </HEAD> <BODY> <? $Last ...

  9. bootstrap的tab中,echarts 图表宽度设为100%之后,会出现图表宽带变为100px的情况。只有第一个正常

    1.原因 echarts官方解释是 Tip: 有时候图表会放在多个标签页里,那些初始隐藏的标签在初始化图表的时候因为获取不到容器的实际高宽,可能会绘制失败,因此在切换到该标签页时需要手动调用resiz ...

  10. 两种好用的清除浮动的小技巧(clearfix hack)

    方法一:使用内容生成的方式清除浮动 这种方法不能解决margin在垂直边界上的叠加问题,如果不涉及margin的边界叠加问题使用这种方法清除浮动就行了 . /* :after 选择器向选定的元素之后插 ...