裸最小割(模板)。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
queue<int> q;
const int inf=0x7f7f7f7f;
int read()
{
char ch=getchar();int f=0;
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9'){f=(f<<1)+(f<<3)+ch-'0';ch=getchar();}
return f;
}
int head[10005],tot,s,a[105][105],t,n,m,ans,dis[10005];
struct node
{
int from;
int to;
int next;
int w;
}edge[200005];
void add(int u,int v,int w)
{
edge[tot].from=u;
edge[tot].to=v;
edge[tot].w=w;
edge[tot].next=head[u];
head[u]=tot++;
}
bool bfs()
{
memset(dis,-1,sizeof(dis));
q.push(s);
dis[s]=0;
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=head[x];i!=-1;i=edge[i].next)
{
if(edge[i].w&&dis[edge[i].to]==-1)
{
dis[edge[i].to]=dis[x]+1;
q.push(edge[i].to);
}
}
}
if(dis[t]==-1)
return 0;
return 1;
}
int dfs(int x,int flow)
{
if(!flow||x==t)
return flow;
int ret=0;
for(int i=head[x];i!=-1;i=edge[i].next)
{
if(dis[edge[i].to]==dis[x]+1)
{
int f=dfs(edge[i].to,min(flow,edge[i].w));
edge[i].w-=f;edge[i^1].w+=f;
ret+=f;flow-=f;
if(!flow)
break;
}
}
if(!ret)
dis[x]=-1;
return ret;
}
void dinic()
{
while(bfs())
{
ans+=dfs(s,0x7f7f7f7f);
}
}
int main()
{
memset(head,-1,sizeof(head));
n=read(),m=read(),s=0,t=n*m+1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
a[0][j]=3;a[n+1][j]=3;
a[i][j]=read();
}
a[i][0]=3;
a[i][m+1]=3;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]==1||a[i][j]==0)
{
if(a[i-1][j]==2||a[i-1][j]==0)
{
add((i-1)*m+j,(i-2)*m+j,1);
add((i-2)*m+j,(i-1)*m+j,0);
}
if(a[i][j-1]==2||a[i][j-1]==0)
{
add((i-1)*m+j,(i-1)*m+j-1,1);
add((i-1)*m+j-1,(i-1)*m+j,0);
}
if(a[i][j+1]==2||a[i][j+1]==0)
{
add((i-1)*m+j,(i-1)*m+j+1,1);
add((i-1)*m+j+1,(i-1)*m+j,0);
}
if(a[i+1][j]==2||a[i+1][j]==0)
{
add((i-1)*m+j,i*m+j,1);
add(i*m+j,(i-1)*m+j,0);
}
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]==2)
{
add((i-1)*m+j,t,inf);
add(t,(i-1)*m+j,0);
}
if(a[i][j]==1)
{
add(s,(i-1)*m+j,inf);
add((i-1)*m+j,s,0);
}
}
}
dinic();
cout<<ans;
}