BZOJ4808馬——二分圖最大獨立集
阿新 • • 發佈:2018-07-12
過去 正整數 這一 多個 情況 highlight nbsp ace pri
一行,兩個正整數N和M。
接下來N行,每行M個數,要麽為0,表示沒壞,要麽為1,表示壞了。
N<=200,M<=200
0 1 0
0 1 0
題目描述
眾所周知,馬後炮是中國象棋中很厲害的一招必殺技。"馬走日字"。本來,如果在要去的方向有別的棋子擋住(俗 稱"蹩馬腿"),則不允許走過去。為了簡化問題,我們不考慮這一點。馬跟馬顯然不能在一起打起來,於是rly在 一天再次借來了許多許多的馬在棋盤上擺了起來……但這次,他實在沒興趣算方案數了,所以他只想知道在N×M的 矩形方格中擺馬使其互不吃到的情況下的最多個數。但是,有一個很不幸的消息,rly由於玩得太Happy,質量本來 就不好的棋盤被rly弄壞了,不過幸好只是破了其中的一些格子(即不能再放子了),問題還是可以繼續解決的。輸入
輸出
一行,輸出最多的個數。樣例輸入
2 30 1 0
0 1 0
樣例輸出
2 這道題和BZOJ3175是一樣的題,黑白染色之後跑二分圖最大匹配,用矩陣大小-1的數目-二分圖最大匹配數。#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #include<cmath> 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<r) { 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); }
BZOJ4808馬——二分圖最大獨立集