还是一道经典的题
对棋盘黑白染色
由于马只能从黑格跳到白格或者反过来,因此原图必然是二分图
建图,连边,求独立集即可
代码如下:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
inline int read() {
int X=0,w=1;char ch=0;
while(ch>'9'||ch<'0')ch=getchar();
while(ch<='9'&&ch>='0') X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return X*w;
}
struct edge
{
int v,p,l;
}e[1000010];
int n,m,s=1,t,top=1,head[40010],cur[40010],d[40010],q[40010];
const int mov[8][2]={{1,2},{2,1},{-1,2},{2,-1},{1,-2},{-2,1},{-1,-2},{-2,-1}};
char ch[210];
bool b[201][201];
inline void addedge(int u,int v)
{
e[++top]=(edge){v,head[u],1};
head[u]=top;
e[++top]=(edge){u,head[v],0};
head[v]=top;
}
bool bfs()
{
memset(q,0,sizeof(q));
memset(d,0,sizeof(d));
int qh=1,qt=0;
d[s]=1;
q[++qt]=s;
while(qh<=qt)
{
int u=q[qh++];
for(register int i=head[u];i;i=e[i].p)
{
int v=e[i].v;
if(e[i].l&&(!d[v]))
{
d[v]=d[u]+1;
q[++qt]=v;
}
}
}
return d[t];
}
int dfs(int u,int delta)
{
if(u==t)
{
return delta;
}
register int ret=0;
for(int &i=cur[u];i;i=e[i].p)
{
if(e[i].l&&(d[e[i].v]==d[u]+1))
{
int dd=dfs(e[i].v,min(e[i].l,delta-ret));
ret+=dd;
e[i].l-=dd;
e[i^1].l+=dd;
if(ret==delta)break;
}
}
if(ret==0)
{
d[u]=-1;
}
return ret;
}
int Dinic()
{
int ret=0;
while(bfs())
{
memcpy(cur,head,sizeof(head));
ret+=dfs(s,INF);
}
return ret;
}
int main()
{
freopen("knight.in","r",stdin);
freopen("knight.out","w",stdout);
cin>>n>>m;
t=2+n*n;
for(int i=1;i<=m;i++)
{
int x=read(),y=read();
b[x][y]=1;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(b[i][j])continue;
if((i%2)^(j%2))
{
addedge(s,(i-1)*n+j+1);
for(int k=0;k<8;k++)
{
int x=i+mov[k][0],y=j+mov[k][1];
if((x>=1)&&(x<=n)&&(y>=1)&&(y<=n)&&(!b[x][y]))
{
addedge((i-1)*n+j+1,(x-1)*n+y+1);
}
}
}
else
{
addedge((i-1)*n+j+1,t);
}
}
}
cout<<n*n-Dinic()-m<<endl;
return 0;
}