最小割,每个格子边容量为1,所以最大流=最小割
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int map[210][210];
int const inf = 1<<30;
struct edge
{
int u,v,flow,next;
} e[444444];
int ecnt;
int head[100000];
void addedge(int u,int v,int flow)
{
e[ecnt].u = u;
e[ecnt].v = v;
e[ecnt].flow = flow;
e[ecnt].next = head[u];
head[u] = ecnt++;
e[ecnt].u = v;
e[ecnt].v = u;
e[ecnt].flow = 0;
e[ecnt].next = head[v];
head[v] = ecnt++;
}
int pre[100000],cur[100000],gap[100000],dis[100000];
int sap(int s,int t)
{
int flow = 0,aug = inf,u;
bool flag;
for(int i=0; i<=t; i++)
cur[i]=head[i],gap[i]=dis[i]=0;
gap[0] = t+1;
u = pre[s] = s;
while(dis[s]<t+1)
{
flag = false;
for(int &j=cur[u]; j!=-1; j=e[j].next)
{
int v = e[j].v;
if(e[j].flow>0&&dis[u]==dis[v]+1)
{
flag = true;
if(aug > e[j].flow) aug = e[j].flow;
pre[v] = u;
u = v;
if(u==t)
{
flow+=aug;
while(u!=s)
{
u = pre[u];
e[cur[u]].flow -= aug;
e[cur[u]^1].flow += aug;
}
aug = inf;
}
break;
}
}
if(flag) continue;
int mindis = t+1;
for(int j = head[u]; j!=-1; j=e[j].next)
{
int v = e[j].v;
if(e[j].flow > 0 && dis[v] < mindis )
mindis = dis[v],cur[u] = j;
}
if((--gap[dis[u]])==0) return flow;
gap[dis[u] = mindis + 1 ]++;
u = pre[u];
}
return flow;
}
int main()
{
int n,m;
ecnt = 0;
int cas = 0;
while(~scanf("%d%d",&n,&m))
{
memset(head,-1,sizeof(head));
for (int i = 1; i<=n; i++)
for (int j = 1; j<=m; j++)
{
scanf("%d",&map[i][j]);
if(i!=1)
addedge((i-1)*m+j,(i-2)*m+j,1);
if(i!=n)
addedge((i-1)*m+j,i*m+j,1);
if(j!=1)
addedge((i-1)*m+j,(i-1)*m+j-1,1);
if(j!=m)
addedge((i-1)*m+j,(i-1)*m+j+1,1);
if(map[i][j]==1)
addedge(0,(i-1)*m+j,inf);
if(map[i][j]==2)
addedge((i-1)*m+j,n*m+1,inf);
}
sap(0,n*m+1);
for (int i = 0; i<ecnt; i+=2)
{
if(e[i].flow==0)e[i].flow = 1,e[i^1].flow = 0;
else e[i].flow = inf,e[i^1].flow = 0;
}
printf("Case %d:\n",++cas);
printf("%d\n",sap(0,n*m+1));
}
}