[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 }

浙公网安备 33010602011771号