title
LUOGU 3355
Title Description
in a on a chess board squares, MA (Knight) can attack a checkerboard as shown in FIG. Some squares on a chessboard set up obstacles, Knight allowed to enter
for a given chess board and obstacles squares logo, the maximum number of knights can be placed on the board computing, so that they do not attack each other mutual
Input and output format
input format:
The first line has two positive integers n and m (1 <= n <= 200, 0 <= m <n2), each represent the size of the board and obstacles. The next position of m rows are given disorder. Each line of two positive integer representing the grid coordinates of the disorder.
Output formats:
The calculated number of output coexistence Knight
Input Output Sample
Input Sample # 1:
3 2
1 1
3 3
Output Sample # 1:
5
analysis
Simple meaning of the questions:
Seeking WITH OBSTACLES chessboard how many horses can put that between any two can not attack each other.
It is one of the largest independent set of problems, routine. .
First, each horse can only attack with their different colors of plaid. Consider a bipartite graph. .
Routines or old, can attack each other between the lattice even one edge, and then find the maximum independent set bipartite graph can. .
Since (bipartite graph) = maximum independent set of points - the maximum matching , so we simply requires the largest match enough. .
Step detailed map building step and grid access issues are almost the same, this will not go into details. .
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;
}