LUOGU P3355 骑士共存问题(二分图最大独立集)
传送门
因为骑士只能走"日"字,所以一定是从一个奇点到偶点或偶点到奇点,那么这就是一张二分图,题目要求的其实就是二分图的最大独立集。最大独立集=n-最大匹配。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int MAXN = 205*205; //const int MAXM = 205*205; const int MAXM = 8*MAXN; inline int rd(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f?x:-x; } int xx[8]={2,1,-1,-2,-2,-1,1,2},yy[8]={1,2,2,1,-1,-2,-2,-1}; int n,m,head[MAXN],cnt,vis[MAXN],match[MAXN]; int to[MAXM<<1],nxt[MAXM<<1],num,ans; bool ban[205][205]; inline void add(int bg,int ed){ // cout<<bg<<" "<<ed<<endl; to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt; } inline void bfs(int x,int y){ for(register int i=0;i<=7;i++){ int ii=xx[i]+x,jj=yy[i]+y; if(ii<1 || ii>n || jj<1 || jj>n || ban[ii][jj]) continue; add((x-1)*n+y,(ii-1)*n+jj); } } bool dfs(int x){ for(register int i=head[x];i;i=nxt[i]){ int u=to[i];if(vis[u]==num) continue; vis[u]=num; if(!match[u] || dfs(match[u])) {match[u]=x;return true;} } return false; } int main(){ n=rd(),m=rd();int x,y; for(register int i=1;i<=m;i++){ x=rd(),y=rd(); ban[x][y]=1; } for(register int i=1;i<=n;i++) for(register int j=(1+((i-1)&1));j<=n;j+=2) if(!ban[i][j]) bfs(i,j); for(register int i=1;i<=n;i++) for(register int j=(1+((i-1)&1));j<=n;j+=2) if(!ban[i][j]) num++,ans+=dfs((i-1)*n+j); cout<<(n*n-m)-ans; return 0; }