POJ 2448 Chessboard

思路:二分图匹配。 相邻两个格子, 行数 + 列数 一定是一个奇数一个偶数, 由此将格子分成两派, 匹配即可。  可以用最大流, 但是匈牙利算法更快, 而且代码短。

细节参见代码:

[cpp]  view plain  copy
 
  1. #include<cstdio>  
  2. #include<cstring>  
  3. #include<algorithm>  
  4. #include<iostream>  
  5. #include<string>  
  6. #include<vector>  
  7. #include<stack>  
  8. #include<bitset>  
  9. #include<cstdlib>  
  10. #include<cmath>  
  11. #include<set>  
  12. #include<list>  
  13. #include<deque>  
  14. #include<map>  
  15. #include<queue>  
  16. #define Max(a,b) ((a)>(b)?(a):(b))  
  17. #define Min(a,b) ((a)<(b)?(a):(b))  
  18. using namespace std;  
  19. typedef long long ll;  
  20. typedef long double ld;  
  21. const ld eps = 1e-9, PI = 3.1415926535897932384626433832795;  
  22. const int mod = 1000000000 + 7;  
  23. const int INF = 0x3f3f3f3f;  
  24. // & 0x7FFFFFFF  
  25. const int seed = 131;  
  26. const ll INF64 = ll(1e18);  
  27. const int maxn = 1500;  
  28. int T,n,m,k;  
  29. vector<int> g[maxn];  
  30. int from[maxn], tot, x, y;  
  31. bool use[maxn];  
  32. bool match(int x) {  
  33.     int len = g[x].size();  
  34.     for(int i = 0; i < len; i++)  
  35.     if(!use[g[x][i]]) {  
  36.         use[g[x][i]] = true;  
  37.         if(from[g[x][i]] == -1 || match(from[g[x][i]])) {  
  38.             from[g[x][i]] = x;  
  39.             return true;  
  40.         }  
  41.     }  
  42.     return false;  
  43. }  
  44. int hungary(int n) {  
  45.     tot = 0;  
  46.     memset(from, -1, sizeof(from));  
  47.     for(int i = 1; i <= n; i++) {  
  48.         memset(use, 0, sizeof(use));  
  49.         if(match(i)) ++tot;  
  50.     }  
  51.     return tot;  
  52. }  
  53.   
  54. int getid(int r, int c) {  
  55.     return (r - 1) * m + c;  
  56. }  
  57. bool vis[55][55];  
  58. int dx[] = {0, 1, 0, -1};  
  59. int dy[] = {1, 0, -1, 0};  
  60. int main() {  
  61.     while(~scanf("%d%d%d",&n,&m,&k)) {  
  62.         memset(vis, falsesizeof(vis));  
  63.         for(int i = 0; i < k; i++) {  
  64.             scanf("%d%d",&x,&y);  
  65.             vis[y][x] = true;  
  66.         }  
  67.         int res = n * m - k;  
  68.         if(res & 1) {  
  69.             printf("NO\n");  
  70.             continue;  
  71.         }  
  72.         for(int i = 1; i <= n; i++) {  
  73.             for(int j = 1; j <= m; j++) {  
  74.                 if(vis[i][j]) continue;  
  75.                 int id1 = getid(i, j);  
  76.                 if((i + j) & 1) continue;  
  77.                 for(int l = 0; l < 4; l++) {  
  78.                     int x = i + dx[l];  
  79.                     int y = j + dy[l];  
  80.                     if(x < 1 || x > n || y < 1 || y > m || vis[x][y]) continue;  
  81.                     int id2 = getid(x, y);  
  82.                     g[id1].push_back(id2);  
  83.                 }  
  84.             }  
  85.         }  
  86.         int ans = hungary(n * m);  
  87.         if(ans == res / 2) printf("YES\n");  
  88.         else printf("NO\n");  
  89.     }  
  90.     return 0;  
  91. }  

你可能感兴趣的:(POJ 2448 Chessboard)