题目描述
“狼爱上羊啊爱的疯狂,谁让他们真爱了一场;狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆。可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已。所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养。 通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变得非常暴躁,不利于他们的成长。 Orez想要添加篱笆的尽可能的短。当然这个篱笆首先得保证不能改变狼羊的所属领地,再就是篱笆必须修筑完整,也就是说必须修建在单位格子的边界上并且不能只修建一部分。
输入输出格式
输入格式:
文件的第一行包含两个整数n和m。接下来n行每行m个整数,1表示该格子属于狼的领地,2表示属于羊的领地,0表示该格子不是任何一只动物的领地。
输出格式:
文件中仅包含一个整数ans,代表篱笆的最短长度。
输入输出样例
输入样例#1:
2 2
2 2
1 1
输出样例#1:
2
说明
数据范围
10%的数据 n,m≤3
30%的数据 n,m≤20
100%的数据 n,m≤100
最小割的模型
一开始傻逼了。。上来就把正解否定了。。
源点向狼连边
狼向羊连边(狼吃羊hhh)
羊向汇点连边
空地之间互相连边
狼向空地连边
空地向羊连边
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=,INF=*1e9+;
inline char nc()
{
static char buf[MAXN],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,,MAXN,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
char c=nc();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=nc();}
while(c>=''&&c<=''){x=x*+c-'';c=nc();}
return x*f;
}
int S=,T=;
struct node
{
int u,v,flow,nxt;
}edge[MAXN*];
int head[MAXN],cur[MAXN],num=;
inline void add_edge(int x,int y,int z)
{
edge[num].u=x;
edge[num].v=y;
edge[num].flow=z;
edge[num].nxt=head[x];
head[x]=num++;
}
inline void AddEdge(int x,int y,int z)
{
add_edge(x,y,z);
add_edge(y,x,);
}int deep[MAXN];
inline bool BFS()
{
memset(deep,,sizeof(deep));
deep[S]=;
queue<int>q;
q.push(S);
while(q.size()!=)
{
int p=q.front();
q.pop();
for(int i=head[p];i!=-;i=edge[i].nxt)
if(!deep[edge[i].v]&&edge[i].flow)
{
deep[edge[i].v]=deep[p]+;q.push(edge[i].v);
if(edge[i].v==T) return ;
}
}
return deep[T];
}
int DFS(int now,int nowflow)
{
if(now==T||nowflow<=) return nowflow;
int totflow=;
for(int &i=cur[now];i!=-;i=edge[i].nxt)
{
if(deep[edge[i].v]==deep[now]+&&edge[i].flow)
{
int canflow=DFS(edge[i].v,min(nowflow,edge[i].flow));
edge[i].flow-=canflow;edge[i^].flow+=canflow;
totflow+=canflow;
nowflow-=canflow;
if(nowflow<=) break;
}
}
return totflow;
}
int Dinic()
{
int ans=;
while(BFS())
{
memcpy(cur,head,sizeof(head));
ans+=DFS(S,INF);
}
return ans;
}
int xx[]={,-,+,,},yy[]={,,,-,+};
int a[][],belong[][];
int N,M;
int main()
{
#ifdef WIN32
freopen("a.in","r",stdin);
#else
#endif
memset(head,-,sizeof(head));
N=read();M=read();T=N*M+;
for(int i=;i<=N;i++)
for(int j=;j<=M;j++)
a[i][j]=read(),belong[i][j]=(i-)*M + j;
for(int i=;i<=N;i++)
for(int j=;j<=M;j++)
{
if(a[i][j]==)
{
AddEdge(S,belong[i][j],INF);
for(int k=;k<=;k++)
if( i+xx[k] >= && i+xx[k] <= N && j+yy[k] >= && j+yy[k]<=M && a[i][j] != a[i+xx[k]][j+yy[k]])
AddEdge(belong[i][j],belong[i+xx[k]][j+yy[k]],);
}
else if(a[i][j]==)
{
AddEdge(belong[i][j],T,INF);
for(int k=;k<=;k++)
if( i+xx[k] >= && i+xx[k] <= N && j+yy[k] >= && j+yy[k]<=M && a[i+xx[k]][j+yy[k]] == )
AddEdge(belong[i+xx[k]][j+yy[k]],belong[i][j],);
}
else
{
for(int k=;k<=;k++)
if( i+xx[k] >= && i+xx[k] <= N && j+yy[k] >= && j+yy[k]<=M && a[i+xx[k]][j+yy[k]] == )
AddEdge(belong[i][j],belong[i+xx[k]][j+yy[k]],);
}
}
printf("%d",Dinic());
return ;
}