在一个 n ∗ n n*n n∗n 个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。
棋盘上某些方格设置了障碍,骑士不得进入。
![QQ截图20200727153405.png](https://img-blog.csdnimg.cn/img_convert/f3d647c137e8b2ac5de7844bc86bd39a.png)
对于给定的 n ∗ n n*n n∗n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击。
输入格式
第一行有 2 2 2 个正整数 n n n 和 m m m,分别表示棋盘的大小和障碍数。
接下来的 m m m 行给出障碍的位置。每行 2 2 2 个正整数,表示障碍的方格坐标。
输出格式
输出可以共存的最大骑士数量。
数据范围
1
≤
n
≤
200
1 \le n \le 200
1≤n≤200,
0
≤
m
≤
n
2
0 \le m \le n^2
0≤m≤n2
输入样例:
3 2
1 1
3 3
输出样例:
5
思路
很明显是最大权独立集。
我们同时也发现所有偶点(横坐标+纵坐标是偶数的点)和奇点二者能构成二分图,因为🐎都是从奇点跳到偶点。(或者相反)
注意:你这边从奇点跳到偶点设为无穷和偶点到奇点设为无穷是一样样的。
以上是边数计算以及建图。
代码
//这个就是典型的最大权独立集
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N = 40010,M = 400010,INT = 1e8;
int e[M],ne[M],f[M],h[N],idx;
int cur[N],d[N];
int dx[]={1,2,2,1,-1,-2,-2,-1};
int dy[]={2,1,-1,-2,-2,-1,1,2};
int n,m,S,T;
bool g[210][210];//判断是否为障碍物
int tot;
int get(int x,int y){
return (x-1)*n+y;
}
void add(int a,int b,int c){
e[idx]=b,f[idx]=c,ne[idx]=h[a],h[a]=idx++;
e[idx]=a,f[idx]=0,ne[idx]=h[b],h[b]=idx++;
}
bool bfs(){
queue<int>q;
q.push(S);
memset(d,-1,sizeof d);
d[S]=0,cur[S]=h[S];
while(q.size()){
int t=q.front();
q.pop();
for(int i=h[t];~i;i=ne[i]){
int ver=e[i];
if(d[ver]==-1&&f[i]){
d[ver]=d[t]+1;
cur[ver]=h[ver];
if(ver==T)return true;
q.push(ver);
}
}
}
return false;
}
int find(int u,int lim){
if(u==T)return lim;
int flow=0;
for(int i=h[u];~i&&flow<lim;i=ne[i]){
int ver=e[i];
cur[u]=i;
if(d[ver]==d[u]+1&&f[i]){
int t=find(ver,min(f[i],lim-flow));
if(!t)d[ver]=-1;
f[i]-=t,f[i^1]+=t,flow+=t;
}
}
return flow;
}
int dinic(){
int r=0,flow;
while(bfs())while(flow=find(S,INT))r+=flow;
return r;
}
int main(){
cin>>n>>m;
memset(h,-1,sizeof h);
S=0,T=n*n+1;
while(m--){
int a,b;
cin>>a>>b;
g[a][b]=true;
}
//遍历每个点
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(g[i][j])continue;
if(i+j&1){
//奇点(其实偶点连好像也是对称的)
add(S,get(i,j),1);
for(int k=0;k<8;k++){
int a=dx[k]+i,b=dy[k]+j;
if(a<1||b<1||a>n||b>n||g[a][b])continue;
add(get(i,j),get(a,b),INT);
}
}else{
add(get(i,j),T,1);
}
tot++;
}
}
cout<<tot-dinic();
return 0;
}