分析:
二分图最大独立集 黑白染色
然后观察图 发现骑士在奇数行奇数列 就会跳到奇数行偶数列 或偶数行奇数列
骑士在偶数行偶数列同理 反过来跳也同理
那就要分奇偶行列连边 这题没有重复的障碍 所以直接跑
D
i
n
i
c
Dinic
Dinic
最后
a
n
s
=
n
×
n
−
m
−
m
a
x
f
l
o
w
ans=n\times n-m-maxflow
ans=n×n−m−maxflow即可 加上弧优化
CODE:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
const int N=2e5+5,inf=0x7fffffff;
struct node{
int to,next,k;
}a[N*10];
int n,m,head[N],tot=1,S,T,dep[N],cur[N];
int dx[10]={0,1,1,-1,-1,2,2,-2,-2},dy[10]={0,2,-2,2,-2,1,-1,1,-1};
bool ovo[205][205];
void add(int x,int y,int k)
{
a[++tot]=(node){y,head[x],k};
head[x]=tot;
}
bool bfs()
{
memset(dep,0,sizeof dep);
queue<int> q;
q.push(S);
dep[S]=1;
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=head[x];i;i=a[i].next)
{
int qwq=a[i].to;
if(!dep[qwq]&&a[i].k)
{
dep[qwq]=dep[x]+1;
q.push(qwq);
}
}
}
return dep[T];
}
int Dinic(int x,int flow)
{
if(x==T||!flow) return flow;
int link=0;
for(int i=cur[x];i;i=a[i].next)
{
cur[x]=i;
int qwq=a[i].to;
if(dep[qwq]==dep[x]+1&&a[i].k)
{
int res=Dinic(qwq,min(flow,a[i].k));
if(res)
{
link+=res;
flow-=res;
a[i^1].k+=res;
a[i].k-=res;
if(!flow) break;
}
}
}
return link;
}
int work()
{
int res=0;
while(bfs())
{
memcpy(cur,head,sizeof head);
res+=Dinic(S,inf);
}
return res;
}
int main(){
scanf("%d%d",&n,&m);
S=0;
T=n*n+1;
for(int i=1,x,y;i<=m;i++)
{
scanf("%d%d",&x,&y);
ovo[x][y]=1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
int qwq=(i-1)*n+j;
if((i+j)&1)
add(S,qwq,1),add(qwq,S,0);
else
add(qwq,T,1),add(T,qwq,0);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(ovo[i][j]) continue;
int qwq=(i-1)*n+j;
if((i+j)&1)
for(int k=1;k<=8;k++)
{
int xx=dx[k]+i,yy=dy[k]+j;
if(xx<1||xx>n||yy<1||yy>n||ovo[xx][yy]) continue;
int qaq=(xx-1)*n+yy;
add(qwq,qaq,1);
add(qaq,qwq,0);
}
}
int ans=n*n-m-work();
printf("%d",ans);
return 0;
}