P3355 骑士共存问题 题解

Link

P3355 骑士共存问题

Solve

对棋盘进行染色,黑白节点分别作为二分图的左右部节点。

对于一个在白色节点的马来说,一定在一步之内不能跳到另外一个白色节点

则通过"日"在相对应的节点之间建边

求上述二分图的的最大独立子集就是答案

Code

#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int MAXN = 1000000;
const int nxt_x[8]={-1,-2,-2,-1,1,2,2,1};
const int nxt_y[8]={-2,-1,1,2,2,1,-1,-2};
int n,m,cnt,ans;
bool Map[2001][2001];
bool used[100001];
int match[100001],head[MAXN];
vector<int> node;
struct Edge
{
    int next,to;
}e[MAXN];
inline void add(int u,int v)
{
    cnt++;
    e[cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt;
}
bool Find(int u)
{
    for(int i=head[u];i;i=e[i].next)
    {
        int v=e[i].to;
        if(!used[v])
        {
            used[v]=1;
            if(match[v]==-1 || Find(match[v]))
            {
                match[v]=u;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
	freopen("P3355.in","r",stdin);
	freopen("P3355.out","w",stdout); 
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int x,y;
        cin>>x>>y;
        Map[x][y]=1;
    }
    for(int x=1;x<=n;x++)
        for(int y=1;y<=n;y++)
            if(!Map[x][y] && (x+y)%2)
            {
            	node.push_back(n*(x-1)+y);
                for(int i=0;i<8;i++)
                {
                    int to_x=x+nxt_x[i];
                    int to_y=y+nxt_y[i];
                    if(to_x<1 || to_x>n || to_y<1 || to_y>n) continue;
                    if(!Map[to_x][to_y])
                        add(n*(x-1)+y,n*(to_x-1)+to_y);
                }	
            }
    memset(match,-1,sizeof(match));
    for(int i=0;i<node.size();i++)
    {
        memset(used,0,sizeof(used));
        ans+=Find(node[i]);
    }
    cout<<n*n-m-ans;
    return 0;
}
posted @ 2020-11-03 10:22  Martian148  阅读(91)  评论(0编辑  收藏  举报