版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/90737835
title
LUOGU 3355
题目描述
在一个 个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘上某些方格设置了障碍,骑士不得进入
对于给定的 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击
输入输出格式
输入格式:
第一行有 2 个正整数n 和 m (1<=n<=200, 0<=m<n2),分别表示棋盘的大小和障碍数。接下来的 m 行给出障碍的位置。每行 2 个正整数,表示障碍的方格坐标。
输出格式:
将计算出的共存骑士数输出
输入输出样例
输入样例#1:
3 2
1 1
3 3
输出样例#1:
5
analysis
简略题意:
求带障碍的 的国际象棋棋盘可以放多少个马,使得两两之间互相不能攻击。
又是一个最大独立集问题,套路。。
首先每个马只能攻击与自己颜色不同的格子。考虑二分图。。
还是老套路,将可以互相攻击的格子之间连一条边,然后求 二分图的最大独立集 即可。。
因为 (二分图)最大独立集 = 点数 - 最大匹配,所以我们只需要求出最大匹配就好了。。
详细的建图步骤和方格取数问题的步骤几乎一样,在此就不赘述了。。
code
#include<bits/stdc++.h>
using namespace std;
const int maxn=4e4+10,maxm=4e5+10,maxk=210,inf=1e9;
const int dx[]={-2,-1,1,2,2,1,-1,-2},dy[]={1,2,2,1,-1,-2,-2,-1};
char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
x=0;
T f=1, ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
template<typename T>inline void write(T x)
{
if (!x) { putchar('0'); return ; }
if (x<0) putchar('-'),x=-x;
T num=0,ch[20];
while (x) ch[++num]=x%10+48,x/=10;
while (num) putchar(ch[num--]);
}
int ver[maxm<<1],edge[maxm<<1],Next[maxm<<1],head[maxn],len=1;
inline void add(int x,int y,int z)
{
ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
ver[++len]=x,edge[len]=0,Next[len]=head[y],head[y]=len;
}
int s,t;
int dist[maxn];
inline bool bfs()
{
queue<int>q;
memset(dist,0,sizeof(dist));
q.push(s);dist[s]=1;
while (!q.empty())
{
int x=q.front();
q.pop();
for (int i=head[x]; i; i=Next[i])
{
int y=ver[i];
if (edge[i] && !dist[y])
{
dist[y]=dist[x]+1;
if (y==t) return 1;
q.push(y);
}
}
}
return 0;
}
inline int get(int x,int low)
{
if (x==t) return low;
int tmp=low;
for (int i=head[x]; i; i=Next[i])
{
int y=ver[i];
if (edge[i] && dist[y]==dist[x]+1)
{
int a=get(y,min(tmp,edge[i]));
if (!a) dist[y]=0;
edge[i]-=a;
edge[i^1]+=a;
if (!(tmp-=a)) break;
}
}
return low-tmp;
}
int n,m;
inline int hash(int i,int j)
{
return (i-1)*n+j;
}
bool ban[maxk][maxk];
int main()
{
read(n);read(m);
s=0,t=hash(n,n)+1;
for (int i=1,x,y; i<=m; ++i) read(x),read(y),ban[x][y]=1;
for (int i=1; i<=n; ++i)
for (int j=1; j<=n; ++j)
{
if (ban[i][j]) continue;
if ((i+j)&1)
{
add(s,hash(i,j),1);
for (int k=0; k<8; ++k)
{
int fx=i+dx[k],fy=j+dy[k];
if (fx<=0 || fx>n || fy<=0 || fy>n || ban[fx][fy]) continue;
add(hash(i,j),hash(fx,fy),inf);
}
}
else add(hash(i,j),t,1);
}
int ans=0;
while (bfs()) ans+=get(s,inf);
write(n*n-m-ans);
return 0;
}