这道题的思路其实还是让我很难受的

让我先从建图讲起

可以先像这样把图染个色


接着对于每个黑点,从源点建一条剩余流量为1的边

对于每个白点,到汇点建一条流量为1的边;

如果一个黑点可以跳到白点,就在图上连一条流量为inf的边

然后跑最小割就可以了

因为割掉这些边以后

代表着剩下的点已经不能够再互相到达了

割掉一条边代表着少一个点

所以最后用点的总数减去已经去掉了的点的数量,减去障碍数量

就是答案

附上代码

#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
const int inf=0x7fffffff;
int zou[8][2]={1,2,2,1,1,-2,-2,1,-1,2,-1,-2,-2,-1,2,-1};
int to[1000005],head[1000005],next[1000005],w[1000005];
int n,m,tot=1,a[205][205],s,t,depth[40005],shu1,shu2,hh[1000005];
queue <int> que;
void add(int x,int y,int z)
{
    to[++tot]=y;
    next[tot]=head[x];
    head[x]=tot;
    w[tot]=z;
}
void deal(int x,int y)
{
    for(int i=0;i<=7;i++)
    {
        int xx=x+zou[i][0];
        int yy=y+zou[i][1];
        if(xx>=1&&xx<=n&&yy>=1&&yy<=n&&!a[xx][yy])
        {
            add((x-1)*n+y,(xx-1)*n+yy,inf);
            add((xx-1)*n+yy,(x-1)*n+y,0);
        }
    }
}
bool bfs()
{
    que.push(s);
    memset(depth,0,sizeof(depth));
    depth[s]=1;
    while(!que.empty())
    {
        int x=que.front();
        que.pop();
        for(int i=head[x];i;i=next[i])
        {
            int y=to[i];
            if(!depth[y]&&w[i])
            {
                depth[y]=depth[x]+1;
                que.push(y);
            }
        }
    }
    if(depth[t]) return true;
    return false;
}
int dinic(int x,int delta)
{
    if(x==t)
    return delta;
    int rest=0;
    for(int i=hh[x];i&δi=next[i])
    if(depth[x]+1==depth[to[i]]&&w[i])
    {
        int y=to[i];
        int ll=dinic(y,min(delta,w[i]));
        w[i]-=ll;
        w[i^1]+=ll;
        delta-=ll;
        rest+=ll;
        hh[x]=i;
    }
    return rest;
}
int main()
{
    cin>>n>>m;
    s=n*n+1;
    t=n*n+2;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&shu1,&shu2);
        a[shu1][shu2]=1;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if((i+j)%2&&!a[i][j])
            {
                add(s,(i-1)*n+j,1);
                add((i-1)*n+j,s,0);
                deal(i,j);
            }
            else if(!((i+j)%2)&&!a[i][j])
            {
                add((i-1)*n+j,t,1);
                add(t,(i-1)*n+j,0);
            }
        }
    }
    int ans=0;
    while(bfs())
    {
        for(int i=1;i<=n*n+2;i++)
        hh[i]=head[i];
        ans+=dinic(s,inf);
    }
    cout<<n*n-m-ans;
    return 0;
}