BZOJ4808马——二分图最大独立集
发布日期:2021-08-26 18:18:27 浏览次数:29 分类:技术文章

本文共 2500 字,大约阅读时间需要 8 分钟。

题目描述

众所周知,马后炮是中国象棋中很厉害的一招必杀技。"马走日字"。本来,如果在要去的方向有别的棋子挡住(俗
称"蹩马腿"),则不允许走过去。为了简化问题,我们不考虑这一点。马跟马显然不能在一起打起来,于是rly在
一天再次借来了许多许多的马在棋盘上摆了起来……但这次,他实在没兴趣算方案数了,所以他只想知道在N×M的
矩形方格中摆马使其互不吃到的情况下的最多个数。但是,有一个很不幸的消息,rly由于玩得太Happy,质量本来
就不好的棋盘被rly弄坏了,不过幸好只是破了其中的一些格子(即不能再放子了),问题还是可以继续解决的。

输入

一行,两个正整数N和M。
接下来N行,每行M个数,要么为0,表示没坏,要么为1,表示坏了。
N<=200,M<=200

输出

一行,输出最多的个数。

样例输入

2 3
0 1 0
0 1 0

样例输出

2
 
 
  这道题和是一样的题,黑白染色之后跑二分图最大匹配,用矩阵大小-1的数目-二分图最大匹配数。
#include
      
       #include
       
        #include
        
         #include
         
          #include
          
           using namespace std;int next[1000001];int to[1000001];int val[1000001];int head[1000001];int tot=1;int q[1000001];int n,k,m;int S,T;int ans;int x,y;int d[1000001];int c[1001][1001];const int dx[]={-2,-1,1,2,2,1,-1,-2};const int dy[]={1,2,2,1,-1,-2,-2,-1};void add(int x,int y,int v){
           
tot++;
next[tot]=head[x];
head[x]=tot;
to[tot]=y;
val[tot]=v;
tot++;
next[tot]=head[y];
head[y]=tot;
to[tot]=x;
val[tot]=0;} bool bfs(int S,int T){
int r=0;
int l=0;
memset(q,0,sizeof(q));
memset(d,-1,sizeof(d));
q[r++]=S;
d[S]=0;
while(l
{
  int now=q[l];
for(int i=head[now];i;i=next[i])
{
if(d[to[i]]==-1&&val[i]!=0)
{
d[to[i]]=d[now]+1;
q[r++]=to[i];
}
}
l++;
}
if(d[T]==-1)
{
return false;
}
else
{
return true;
}}int dfs(int x,int flow){
if(x==T)
{
return flow;
}
int now_flow;
int used=0;
for(int i=head[x];i;i=next[i])
{
if(d[to[i]]==d[x]+1&&val[i]!=0)
{
now_flow=dfs(to[i],min(flow-used,val[i]));
val[i]-=now_flow;
val[i^1]+=now_flow;
used+=now_flow;
if(now_flow==flow)
{
return flow;
}
}
}
if(used==0)
{
d[x]=-1;
}
return used;}void dinic(){
while(bfs(S,T)==true)
{
ans+=dfs(S,0x3f3f3f);
}}int main(){
scanf("%d%d",&n,&m);
S=n*m+16;
T=n*m+28;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&c[i][j]);
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(c[i][j]==0)
{
c[i][j]=(i-1)*m+j;
if((i+j)%2==0)
{
add(S,c[i][j],1);
}
else
{
add(c[i][j],T,1);
}
}
else
{
k++;
c[i][j]=-1;
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(c[i][j]!=-1&&(i+j)%2==0)
{
for(int l=0;l<=7;l++)
{
int fx=dx[l]+i;
int fy=dy[l]+j;
if(fx>0&&fx<=n&&fy>0&&fy<=m&&c[fx][fy]!=-1)
{
add(c[i][j],c[fx][fy],0x3f3f3f);
}
 }
}
}
}
dinic();
printf("%d",n*m-k-ans);}

转载于:https://www.cnblogs.com/Khada-Jhin/p/9301740.html

转载地址:https://blog.csdn.net/weixin_33894640/article/details/92657377 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Log4j 1使用教程
下一篇:Flash游戏抓取,flash网站抓取,网页游戏提取工具

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2023年03月20日 01时14分04秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

最新文章