1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define M 100009 5 #define inf 2139062143 6 using namespace std; 7 int n,m,a[102][102],cnt=1,T,ans,head[M],d[M],q[2*M],next[10*M],u[10*M],v[10*M]; 8 int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0}; 9 bool bfs() 10 { 11 memset(d,0,sizeof(int)*(T+1)); 12 int h=0,t=1; 13 q[1]=0; 14 d[0]=1; 15 for(;h<t;) 16 { 17 h++; 18 int p=q[h]; 19 for(int i=head[p];i;i=next[i]) 20 if(!d[u[i]]&&v[i]) 21 { 22 d[u[i]]=d[p]+1; 23 if(d[T]) 24 return 1; 25 t++; 26 q[t]=u[i]; 27 } 28 } 29 return 0; 30 } 31 int dinic(int s,int f) 32 { 33 if(s==T) 34 return f; 35 int rest=f; 36 for(int i=head[s];i&&rest;i=next[i]) 37 if(v[i]&&d[u[i]]==d[s]+1) 38 { 39 int now=dinic(u[i],min(rest,v[i])); 40 if(!now) 41 d[u[i]]=0; 42 v[i]-=now; 43 v[i^1]+=now; 44 rest-=now; 45 } 46 return f-rest; 47 } 48 void jia1(int a1,int a2,int a3) 49 { 50 cnt++; 51 next[cnt]=head[a1]; 52 head[a1]=cnt; 53 u[cnt]=a2; 54 v[cnt]=a3; 55 return; 56 } 57 void jia(int a1,int a2,int a3) 58 { 59 jia1(a1,a2,a3); 60 jia1(a2,a1,0); 61 return; 62 } 63 int main() 64 { 65 scanf("%d%d",&n,&m); 66 for(int i=1;i<=n;i++) 67 for(int j=1;j<=m;j++) 68 scanf("%d",&a[i][j]); 69 T=n*m+1; 70 for(int i=1;i<=n;i++) 71 for(int j=1;j<=m;j++) 72 { 73 if(a[i][j]==1) 74 jia(0,(i-1)*m+j,inf); 75 if(a[i][j]==2) 76 jia((i-1)*m+j,T,inf); 77 for(int k=0;k<4;k++) 78 { 79 int nx=i+xx[k],ny=j+yy[k]; 80 if(!nx||!ny||nx>n||ny>m) 81 continue; 82 if(a[nx][ny]!=a[i][j]||a[i][j]==0) 83 jia((i-1)*m+j,(nx-1)*m+ny,1); 84 } 85 } 86 for(;bfs();) 87 ans+=dinic(0,0x7fffffff); 88 printf("%d ",ans); 89 return 0; 90 }
最小割,不同的点之间进行连边,空地于空地之间连边,易知最小割极为答案。