1. 程式人生 > 實用技巧 >ICPC Pacific Northwest Regional Contest 2016 Maximum Islands(二分圖最大獨立集)

ICPC Pacific Northwest Regional Contest 2016 Maximum Islands(二分圖最大獨立集)

Maximum Islands

思路:預處理‘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 }