Codevs1922 骑士共存问题
1922 骑士共存问题
题目描述 Description
在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘
上某些方格设置了障碍,骑士不得进入。
对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑
士,使得它们彼此互不攻击。
输入描述
Input Description
第一行有2 个正整数n 和m (1<=n<=200, 0<=m<n^2),
分别表示棋盘的大小和障碍数。接下来的m 行给出障碍的位置。每行2 个正整数,表示障
碍的方格坐标。
输出描述
Output Description
将计算出的共存骑士数输出
样例输入
Sample Input
3 2
1 1
3 3
样例输出
Sample Output
5
数据范围及提示
Data Size & Hint
详见试题
【题解】
卡了半天常还是卡不过去,等以后再用Dinic写吧
先进行黑白染色(此类问题常用),不难发现骑士
只会从黑->白或白->黑,因此我们令X集合为黑,
Y集合为白,从黑->白则连一条边(给黑白格子编 号),
然后找最大独立集即可。注意总的节点数 是没有障碍的
点,做最大匹配的时候也要用没有 障碍的格子的染色
编号。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 6 inline void read(int &x) 7 { 8 x = 0;char ch = getchar(), c = ch; 9 while(ch < '0' || ch > '9') c = ch, ch = getchar(); 10 while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); 11 if(c == '-')x = -x; 12 } 13 14 const int MAXN = 200 + 10; 15 const int dx[8] = {1,-1,2,-2,1,-1,2,-2}; 16 const int dy[8] = {2,-2,1,-1,-2,2,-1,1}; 17 18 int gg[MAXN][MAXN], b[MAXN][MAXN], n, m, lk[200000],bb[200000]; 19 20 struct Edge 21 { 22 int u,v,next; 23 Edge(int _u, int _v, int _next){u = _u;v = _v;next = _next;} 24 Edge(){} 25 }edge[200000]; 26 27 int head[200000]; 28 29 int dfs(int u) 30 { 31 for(int pos = head[u];pos;pos = edge[pos].next) 32 { 33 int v = edge[pos].v; 34 if(bb[v])continue; 35 bb[v] = 1; 36 if(lk[v] == -1 || dfs(lk[v])) 37 { 38 lk[v] = u; 39 return 1; 40 } 41 } 42 return 0; 43 } 44 45 int xiongyali(int white) 46 { 47 int ans = 0; 48 memset(lk, -1, sizeof(lk)); 49 for(register int i = 1;i <= white;++i) 50 { 51 memset(bb, 0, sizeof(bb)); 52 ans += dfs(i); 53 } 54 return ans; 55 } 56 57 int main() 58 { 59 read(n), read(m); 60 register int black, white, i; 61 for(i = 1;i <= m;++ i) 62 { 63 read(black), read(white); 64 b[black][white] = 1; 65 } 66 //X集合:1 白色 Y集合:0 黑色 67 black = white = 0; 68 for(i = 1;i <= n;++ i) 69 for(int j = 1;j <= n;++ j) 70 if(!b[i][j]) 71 if((i + j)&1) gg[i][j] = ++ black; 72 else gg[i][j] = ++ white; 73 register int xx, yy, cnt = 0; 74 for(i = 1;i <= n;++ i) 75 for(int j = 1;j <= n;++ j) 76 if(!((i + j)&1) && !b[i][j]) 77 for(int k = 0;k < 8;++ k) 78 { 79 xx = i + dx[k], yy = j + dy[k]; 80 if(xx <= 0 || yy <= 0 || xx > n || yy > n || b[xx][yy])continue; 81 yy = gg[xx][yy], xx = gg[i][j]; 82 edge[++cnt] = Edge(xx,yy,head[xx]); 83 head[xx] = cnt; 84 } 85 printf("%d", white + black - xiongyali(white)); 86 return 0; 87 }