传送门
对于给定的 n*n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击
这个题运用奇偶性建图,黑白染色,黑连S,白连T,然后跑最大流,求出最小割,用n2 减去即可。
#include
#include
#include
#include
#include
using namespace std;
#define re register
#define gc getchar()
inline int read() {
re int x=0,f=1;re char ch=gc;
while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=gc;}
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=gc;
return x*f;
}
const int N=40010,INF=(1<<29);
struct node {
int next,to,w;
}e[N<<4];
int h[N],n,cnt=1,s,t,m;
inline void add(int u,int v,int w) {
e[++cnt]=(node) {h[u],v,w},h[u]=cnt;
e[++cnt]=(node) {h[v],u,0},h[v]=cnt;
}
#define QXX(u) for(int i=h[u],v;v=e[i].to,i;i=e[i].next)
int deep[N];
inline int bfs() {
queue<int> q;
q.push(s);
// memset(deep,0,sizeof(deep));
for (int i = 1; i <= t; ++i) deep[i] = 0;
deep[s]=1;
while(!q.empty()) {
int u=q.front();
q.pop();
QXX(u) if(e[i].w&&!deep[v]) {
deep[v]=deep[u]+1;
q.push(v);
if(v==t) return 1;
}
}
return 0;
}
int dfs(int u,int flow) {
if(u==t) return flow;
int res=flow;
QXX(u) if(e[i].w&&deep[v]==deep[u]+1) {
int k=dfs(v,min(res,e[i].w));
e[i].w-=k;
e[i^1].w+=k;
res-=k;
}
if(res==flow)
deep[u]=0;
return flow-res;
}
int ans,maxf,a[220][220],k;
int x[]={1,2,+2,+1,-1,-2,-2,-1};
int y[]={2,1,-1,-2,-2,-1,+1,+2};
#define id(i,j) ((i-1)*n+j)
int main() {
// freopen("x.txt","r",stdin);
n=read(),m=read();
for(int i=1;i<=m;++i) {
a[read()][read()]=1;
}
s=n*n+1;
t=s+1;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j) {
if(!a[i][j]) {
re int w=id(i,j);
if((i+j)&1) {
add(s,w,1);
for(int k=0;k<8;++k) {
re int r=x[k]+i;
re int c=y[k]+j;
if(!a[r][c]&&r>0&&r<=n&&c>0&&c<=n)
add(w,id(r,c),INF);
}
}
else add(w,t,1);
}
}
while(bfs()) {
while((ans=dfs(s,INF))) maxf+=ans;
}
cout<<n*n-maxf-m<<endl;
return 0;
}