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 }
90分TLE代码
posted @ 2017-09-23 20:58  嘒彼小星  阅读(223)  评论(0编辑  收藏  举报