BZOJ 4808: 马【二分图】【最大独立集】

Description

众所周知,马后炮是中国象棋中很厉害的一招必杀技。”马走日字”。本来,如果在要去的方向有别的棋子挡住(俗

称”蹩马腿”),则不允许走过去。为了简化问题,我们不考虑这一点。马跟马显然不能在一起打起来,于是rly在

一天再次借来了许多许多的马在棋盘上摆了起来……但这次,他实在没兴趣算方案数了,所以他只想知道在N×M的

矩形方格中摆马使其互不吃到的情况下的最多个数。但是,有一个很不幸的消息,rly由于玩得太Happy,质量本来

就不好的棋盘被rly弄坏了,不过幸好只是破了其中的一些格子(即不能再放子了),问题还是可以继续解决的。

题解

先01黑白染色,然后刷二分图最大独立集。(最大独立集=点数-最大匹配)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 40006
#define maxm 206
#define id(x,y) ((x-1)*m+y)
using namespace std;
inline char nc(){
    static char buf[100000],*i=buf,*j=buf;
    return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++; 
}
inline int _read(){
    char ch=nc();int sum=0;
    while(!(ch>='0'&&ch<='9'))ch=nc();
    while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
    return sum;
}
const int flg2[8][2]={{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1}};
const int flg1[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
int n,m,e,tot,ans,all,c[maxn],lnk[maxn],mat[maxn],son[maxn*8],nxt[maxn*8],
    map[maxm][maxm];
bool vis[maxn];
void add(int x,int y){
    nxt[++tot]=lnk[x];son[tot]=y;lnk[x]=tot;
}
bool check(int x,int y){
    if(x<1||x>n||y<1||y>m)return 0;
    return 1;
}
bool dfs(int x){
    if(!vis[x])return 0;
    vis[x]=0;
    for(int j=lnk[x];j;j=nxt[j]) if(!mat[son[j]]||dfs(mat[son[j]])){
        mat[son[j]]=x;
        return 1;
    }
    return 0;
}
void hungary(){
    for(int i=1;i<=n*m;i++) if(c[i]==0){
        memset(vis,1,sizeof(vis));
        ans+=dfs(i);
    }
}
int main(){
    freopen("horse.in","r",stdin);
    freopen("horse.out","w",stdout);
    n=_read();m=_read();
    for(int i=1;i<=n;i++)
     for(int j=1;j<=m;j++)map[i][j]=_read(),all+=(map[i][j]==0);
    memset(c,255,sizeof(c));c[1]=0;
    for(int i=1;i<=n;i++)
     for(int j=1;j<=m;j++)
      for(int k=0;k<4;k++){
        int x=flg1[k][0]+i,y=flg1[k][1]+j;
        if(check(x,y)&&c[id(x,y)]==-1)c[id(x,y)]=c[id(i,j)]^1;
      }
    for(int i=1;i<=n;i++)
     for(int j=1;j<=m;j++) if(map[i][j]==0&&c[id(i,j)]==0)
      for(int k=0;k<8;k++){
        int x=i+flg2[k][0],y=j+flg2[k][1];
        if(check(x,y)&&map[x][y]==0)add(id(i,j),id(x,y));
      }
    hungary();
    printf("%d\n",all-ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/fyoier/article/details/78500758