/* 这么大的图,差点不敢水。。。。 还是用最小割水了,建图很简单,知道最小割的估计都会,不累赘了 */ #include<cstdio> #include<cstring> const int N=50000; const int M=500000; const int inf=0x7fffffff; int head[N]; int map[201][201]; struct Edge { int v,next,w; } edge[M]; int cnt,n,s,t; void addedge(int u,int v,int w) { edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].v=u; edge[cnt].w=0; edge[cnt].next=head[v]; head[v]=cnt++; } int sap() { int pre[N],cur[N],dis[N],gap[N]; int flow=0,aug=inf,u; bool flag; for(int i=0; i<n; i++) { cur[i]=head[i]; gap[i]=dis[i]=0; } gap[s]=n; u=pre[s]=s; while(dis[s]<n) { flag=0; for(int &j=cur[u]; j!=-1; j=edge[j].next) { int v=edge[j].v; if(edge[j].w>0&&dis[u]==dis[v]+1) { flag=1; if(edge[j].w<aug) aug=edge[j].w; pre[v]=u; u=v; if(u==t) { flow+=aug; while(u!=s) { u=pre[u]; edge[cur[u]].w-=aug; edge[cur[u]^1].w+=aug; } aug=inf; } break; } } if(flag) continue; int mindis=n; for(int j=head[u]; j!=-1; j=edge[j].next) { int v=edge[j].v; if(edge[j].w>0&&dis[v]<mindis) { mindis=dis[v]; cur[u]=j; } } if((--gap[dis[u]])==0) break; gap[dis[u]=mindis+1]++; u=pre[u]; } return flow; } int main() { int m; int cas=1; while(scanf("%d%d",&n,&m)!=EOF) { s=0; t=n*m+1; cnt=0; memset(head,-1,sizeof(head)); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) scanf("%d",&map[i][j]); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) { int te=(i-1)*m+j; if(i<n) addedge(te,te+m,1); if(i>1) addedge(te,te-m,1); if(j<m) addedge(te,te+1,1); if(j>1) addedge(te,te-1,1); if(map[i][j]==1) addedge(te,t,inf); if(map[i][j]==2) addedge(s,te,inf); } n=n*m+2; printf("Case %d:/n",cas++); printf("%d/n",sap()); } return 0; }