题目
在棋盘内放入尽量多的骑士,使他们(马步)互不攻击。
分析
匈牙利算法
但是这次要用网络流最大流,dinic。
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <queue>
using namespace std;
struct node{int y,next,w;}e[500001];
bool v[203][203]; int ls[50001],dis[50001],n,m,ans;
const int dx[8]={1,1,-1,-1,2,2,-2,-2},dy[8]={2,-2,2,-2,1,-1,1,-1};
int in(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void add(int x,int y){
e[++m].y=y; e[m].w=1; e[m].next=ls[x]; ls[x]=m;
e[++m].y=x; e[m].w=0; e[m].next=ls[y]; ls[y]=m;
}
bool bfs(){
for (int i=1;i<=n*n+2;i++) dis[i]=0;
dis[n*n+1]=1; queue<int>q; q.push(n*n+1);
while (q.size()){
int x=q.front(); q.pop();
for (int i=ls[x];i;i=e[i].next)
if (e[i].w>0&&!dis[e[i].y]){
dis[e[i].y]=dis[x]+1;
if (e[i].y==n*n+2) return 1;
q.push(e[i].y);
}
}
return 0;
}
int dfs(int x,int flow)
{
if(x==n*n+2||!flow) return flow;
int rest=0,f;
for(int i=ls[x];i;i=e[i].next)
{
int y=e[i].y;
if(dis[x]+1==dis[y]&&e[i].w)
{
rest+=(f=dfs(y,min(flow-rest,e[i].w)));
e[i].w-=f;e[i^1].w+=f;
}
}
if(!rest) dis[x]=0;
return rest;
}
int main(){
n=in(); m=in(); ans=n*n-m;
while (m--) v[in()][in()]=1; m=1;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (!v[i][j]){
if (!((i+j)&1)){
add(n*n+1,(i-1)*n+j);
for (int k=0;k<8;k++){
int x=i+dx[k],y=j+dy[k];
if (v[x][y]||x<1||x>n||y<1||y>n) continue;
add((i-1)*n+j,(x-1)*n+y);
}
}else add((i-1)*n+j,n*n+2);
}
while (bfs()) ans-=dfs(n*n+1,1e7);
return !printf("%d",ans);
}