思路:预处理‘L’周围包围‘W’。‘L’独自成为岛屿为最优,我们‘L’,‘W’交替处理的图((x+y)%2为同一个集合),分为两个集合,相邻的‘L’和‘W’有边,同一个集合没边,变成二分图的最大独立集问题,得出最多的互不相邻的点就是最大岛屿数量。因为我们匹配的出发点是全图,所以匹配数 = match / 2。
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <vector> 5 #include <queue> 6 7 using namespace std; 8 9 const int N = 50; 10 int mv_x[] = {1, -1, 0, 0}; 11 int mv_y[] = {0, 0, 1, -1}; 12 char mp[N][N]; //地图 13 vector<int > E[N * N]; //边 14 int pre[N * N]; 15 bool vis[N * N]; 16 bool viss[N][N]; //是否访问过 17 bool e[N * N][N * N]; //重复边判定 18 int id[N][N]; //编号 19 int n, m, island, poi; 20 21 inline bool check(int x, int y) 22 { 23 return x >= 0 && x < n && y >= 0 && y < m; 24 } 25 26 void dfs_island(int x, int y) 27 { 28 mp[x][y] = 'W'; 29 for(int p = 0; p < 4; ++p){ 30 int dx = x + mv_x[p]; 31 int dy = y + mv_y[p]; 32 33 if(check(dx, dy) && mp[dx][dy] == 'L'){ 34 dfs_island(dx, dy); 35 } 36 } 37 } 38 39 inline void add(int u, int v) 40 { 41 E[u].push_back(v); 42 E[v].push_back(u); 43 } 44 45 void dfs_cloud(int x, int y) 46 { 47 viss[x][y] = 1; 48 for(int p = 0; p < 4; ++p){ 49 int dx = x + mv_x[p]; 50 int dy = y + mv_y[p]; 51 52 if(check(dx, dy) && mp[dx][dy] == 'C'){ 53 int id1 = min(id[x][y], id[dx][dy]); 54 int id2 = max(id[x][y], id[dx][dy]); 55 if(e[id1][id2] == 0){ 56 e[id1][id2] = 1; 57 add(id1, id2); 58 } 59 if(!viss[dx][dy]){ 60 viss[dx][dy] = 1; 61 dfs_cloud(dx, dy); 62 } 63 } 64 } 65 } 66 67 bool find(int u) 68 { 69 for(auto v : E[u]){ 70 if(vis[v]) continue; 71 vis[v] = 1; 72 if(!pre[v] || find(pre[v])){ 73 pre[v] = u; 74 return true; 75 } 76 } 77 return false; 78 } 79 80 void show() 81 { 82 for(int i = 0; i < n; ++i){ 83 for(int j = 0; j < m; ++j){ 84 cout << mp[i][j]; 85 }cout << endl; 86 } 87 } 88 89 void solve() 90 { 91 92 scanf("%d%d", &n, &m); 93 for(int i = 0; i < n; ++i) scanf("%s", &mp[i]); 94 //预处理L 95 for(int i = 0; i < n; ++i){ 96 for(int j = 0; j < m; ++j){ 97 if(mp[i][j] == 'L'){ 98 for(int p = 0; p < 4; ++p){ 99 int dx = i + mv_x[p]; 100 int dy = j + mv_y[p]; 101 if(check(dx, dy) && mp[dx][dy] == 'C'){ 102 mp[dx][dy] = 'W'; 103 } 104 } 105 } 106 } 107 } 108 109 //统计岛屿个数,编号 110 for(int i = 0; i < n; ++i){ 111 for(int j = 0; j < m; ++j){ 112 if(mp[i][j] == 'L'){ 113 island++; 114 dfs_island(i, j); 115 }else if(mp[i][j] == 'C') id[i][j] = ++poi; 116 } 117 } 118 119 //建图 120 for(int i = 0; i < n; ++i){ 121 for(int j = 0; j < m; ++j){ 122 if(mp[i][j] == 'C'){ 123 dfs_cloud(i, j); 124 } 125 } 126 } 127 128 //匹配 129 int match = 0; 130 for(int i = 0; i < n; ++i){ 131 for(int j = 0; j < m; ++j){ 132 if(!id[i][j]) continue; 133 for(int x = 1; x <= poi; ++x) vis[x] = 0; 134 if(find(id[i][j])) match++; 135 } 136 } 137 138 //printf("island = %d ", island + poi - match / 2); 139 printf("%d ", island + poi - match / 2); 140 } 141 142 143 int main() 144 { 145 146 solve(); 147 148 return 0; 149 }