思路:预处理‘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\n", island + poi - match / 2);
139 printf("%d\n", island + poi - match / 2);
140 }
141
142
143 int main()
144 {
145
146 solve();
147
148 return 0;
149 }
来源:oschina
链接:https://my.oschina.net/u/4399604/blog/4331070