4554: [Tjoi2016&Heoi2016]游戏 二分图匹配

题目链接:

http://www.lydsy.com/JudgeOnline/problem.php?id=4554

题解:

如果没有硬石头的话,就是’*‘点对应的行列建边,然后跑最大匹配

硬石头什么作用?它可以让同一行或同一列存在不只一个炸弹,因此我们可以将一个硬石头的上下拆成两列,左右拆成两行,然后就可以用经典的做法来跑最大匹配了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector>
 5 using namespace std;
 6 
 7 const int maxn = 55;
 8 const int maxs = 2555;
 9 int n, m;
10 
11 char str[maxn][maxn];
12 int _x[maxn][maxn], _y[maxn][maxn];
13 int _r, _c;
14 vector<int> G[maxs];
15 
16 int lef[maxs], _t[maxs];
17 bool match(int u) {
18     for (int j = 0; j < G[u].size(); j++) {
19         int v = G[u][j];
20         if (!_t[v]) {
21             _t[v] = 1;
22             if (lef[v]==-1 || match(lef[v])) {
23                 lef[v] = u;
24                 return true;
25             }
26         }
27     }
28     return false;
29 }
30 
31 int BM() {
32     memset(lef, -1, sizeof(lef));
33     for (int i = 0; i < _r; i++) {
34         memset(_t, 0, sizeof(_t));
35         match(i);
36     }
37     int ret = 0;
38     for (int i = 0; i < _c; i++) {
39         if (lef[i] != -1) ret++;
40     }
41     return ret;
42 }
43 
44 void init() {
45     for (int i = 0; i < maxs; i++) G[i].clear();
46 }
47 
48 int main() {
49     while (scanf("%d%d", &n, &m) == 2 && n) {
50         init();
51         for (int i = 0; i < n; i++) scanf("%s", str[i]);
52         _r = 0, _c = 0;
53         for (int i = 0; i < n; i++) {
54             for (int j = 0; j < m; j++) {
55                 if (str[i][j] == '#') _r++;
56                 else if (str[i][j] == '*') _x[i][j] = _r;
57             }
58             _r++;
59         }
60         for (int j = 0; j < m; j++) {
61             for (int i = 0; i < n; i++) {
62                 if (str[i][j] == '#') _c++;
63                 else if (str[i][j] == '*') _y[i][j] = _c;
64             }
65             _c++;
66         }
67         for (int i = 0; i < n; i++) {
68             for (int j = 0; j < m; j++) {
69                 if (str[i][j] == '*') {
70                     G[_x[i][j]].push_back(_y[i][j]);
71                 }
72             }
73         }
74         printf("%d\n", BM());
75     }
76     return 0;
77 }
78 
79 /*
80 4 4
81 #***
82 *#**
83 **#*
84 xxx#
85 */

 

posted @ 2016-05-20 23:50  fenicnn  阅读(229)  评论(0编辑  收藏  举报