[HEOI2016/TJOI2016]游戏 | 最大匹配

题目:[HEOI2016/TJOI2016]游戏

根剖二分图性质:求解的最大性,匹配的专一性,边的唯一性。在题目中分别反映为:
  1、求最多能放置几枚炸弹。
  2、一个行只能与一个列有交点,一个列只能与一个行有交点。
  3、一个行与列集之间只有一条边相连,一个列与行集之间只有一条边相连。这条相连的边(媒介),就是行与列的交点。

   求最大二分图匹配。我还是喜欢 Hopcroft - carp算法。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <string>
 4 #include <vector>
 5 
 6 const int N = 2500 + 10;
 7 
 8 int read() {
 9     int x = 0, f = 1;
10     char c = getchar();
11     while (!isdigit(c)) {
12         if (c == '-') f = -1;
13         c = getchar();
14     }
15     while (isdigit(c)) {
16         x = (x << 3) + (x << 1) + (c ^ 48);
17         c = getchar();
18     }
19     return x * f;
20 }
21 
22 struct Hungary {
23     int nx, ny, my[N], vis[N];
24     std::vector<int> G[N];
25     
26     void in() {
27         int n = read(), m = read(), mat[60][60] = {}; nx = 0, ny = 0;
28         char s[100] = {};
29         for (int i = 1; i <= n; ++ i) {
30             ++ nx;
31             scanf("%s", s);
32             for (int j = 0; j < m; ++ j) {
33                 if (s[j] == '#') {
34                     mat[i][j + 1] = -1;
35                     if (j > 0 && j < m - 1) ++ nx;
36                 } else if (s[j] == '*') 
37                     mat[i][j + 1] = nx;
38             }
39         }
40         for (int j = 1; j <= m; ++ j) {
41             ++ ny;
42             for (int i = 1; i <= n; ++ i) {
43                 if (mat[i][j] == -1 && i > 1 && i < n)
44                     ++ ny;
45                 else if (mat[i][j] > 0)
46                     G[mat[i][j]].push_back(ny);
47             }
48         }
49     }
50     
51     bool DFS(int u) {
52         int size = G[u].size();
53         for (int i = 0; i < size; ++ i) {
54             int v = G[u][i];
55             if (!vis[v]) {
56                 vis[v] = 1;
57                 if (my[v] == 0 || DFS(my[v])) {
58                     my[v] = u;
59                     return 1;
60                 }
61             }
62         }
63         return 0;
64     }
65     
66     int Maxmatch() {
67         int ans = 0;
68         for (int i = 1; i <= nx; ++ i) {
69             memset(vis, 0, sizeof vis);
70             if (DFS(i)) ++ ans;
71         }
72         return ans;
73     }
74 } H;
75 
76 int main() {
77     H.in();
78     int ans = H.Maxmatch();
79     printf("%d\n", ans);
80     return 0;
81 }
[HEOI2016/TJOI2016]游戏

 

posted @ 2018-02-07 19:19  Milky-Way  阅读(147)  评论(0)    收藏  举报