骑士共存问题
题解:
图就是题解。
黄色格子只能跳到红色格子上。
于是就和方格取数问题一样了。
代码:
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 250 #define ll long long const int inf = 0x3f3f3f3f; const ll Inf = 0x3f3f3f3f3f3f3f3fll; inline int rd() { int f=1,c=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();} return f*c; } int n,m,S,T,hed[N*N],cur[N*N],cnt=-1; bool ban[N][N]; int dx[]={-2,-2,-1,-1,1,1,2,2}; int dy[]={1,-1,2,-2,2,-2,1,-1}; int _id(int x,int y) { return (x-1)*n+y; } bool check(int x,int y) { if(x<1||y<1||x>n||y>n)return 0; if(ban[x][y])return 0; return 1; } struct EG { int to,nxt; ll w; }e[N*N*20]; void ae(int f,int t,ll w) { e[++cnt].to = t; e[cnt].nxt = hed[f]; e[cnt].w = w; hed[f] = cnt; } int dep[N*N]; bool vis[N*N]; queue<int>q; bool bfs() { memset(dep,0x3f,sizeof(dep)); memcpy(cur,hed,sizeof(cur)); dep[S]=0,vis[S]=1;q.push(S); while(!q.empty()) { int u = q.front(); q.pop(); for(int j=hed[u];~j;j=e[j].nxt) { int to = e[j].to; if(e[j].w&&dep[to]>dep[u]+1) { dep[to] = dep[u]+1; if(!vis[to]) { vis[to] = 1; q.push(to); } } } vis[u] = 0; } return dep[T]!=inf; } ll dfs(int u,ll lim) { if(u==T||!lim)return lim; ll fl = 0,f; for(int j=cur[u];~j;j=e[j].nxt) { cur[u] = j; int to = e[j].to; if(dep[to]==dep[u]+1&&(f=dfs(to,min(lim,e[j].w)))) { fl+=f,lim-=f; e[j].w-=f,e[j^1].w+=f; if(!lim)break; } } return fl; } ll dinic() { ll ret = 0; while(bfs())ret+=dfs(S,Inf); return ret; } int main() { n = rd(),m = rd(); S = n*n+1,T = n*n+2; memset(hed,-1,sizeof(hed)); for(int x,y,i=1;i<=m;i++) { x = rd(),y = rd(); ban[x][y] = 1; } ll sum = n*n-m; for(int i=1;i<=n;i++) for(int u,j=1;j<=n;j++) { if(ban[i][j])continue; u = _id(i,j); if((i+j)&1) { ae(S,u,1); ae(u,S,0); for(int x,y,k=0;k<8;k++) { x = i+dx[k],y = j+dy[k]; if(check(x,y)) { int to = _id(x,y); ae(u,to,Inf); ae(to,u,0); } } }else { ae(u,T,1); ae(T,u,0); } } printf("%lld\n",sum-dinic()); return 0; }