题目
在怒江,有一个著名的草原。它还能吸引可爱的羊和它的伙伴们去度假。大灰狼和他的家人知道了这件事,悄悄地躲进了大草坪。作为ZJNU ACM/ICPC团队的一员,我们有义务保护好喜羊羊和它的伙伴们,不被大灰狼打扰。我们决定建造一些长度为1的单位栅栏。任何狼和羊都不能越过篱笆。当然,一个网格只能包含一个动物。
现在,我们要求设置最小的栅栏,让喜羊羊和他的伙伴们免受大灰狼和他的伙伴们的打扰。
输入
有很多情况。
对每一个案例:
N和M(N,M < = 200)
N * M矩阵:
0是空的,1是喜羊羊和他的伙伴,2是大灰狼和他的伙伴。
输出
对每一个案例:
第一行输出“Case p:”,p为第p种情况;
第二行是答案。
Sample Input
4 6
1 0 0 1 0 0
0 1 1 0 0 0
2 0 0 0 0 0
0 2 0 1 1 0
Sample Output
Case 1:
4
喜羊羊向t建容量为4或大于4 INF的边。。。 灰太狼向s建容量为4或大于4 INF的边
代表要从狼出发到羊 所以是最小割
每个格子向相邻的格子建容量为1的边
#include <queue>
#include <cstring>
#include <cstdio>
#define m(a,b) memset(a,b,sizeof a)
using namespace std;
const int N=45000;
const int INF=0x3f3f3f3f;
struct Edge{int to,len,nex;}edge[N*10];
int head[N],d[N];
int tot,s,t;
void add(int from,int to,int len)
{
edge[++tot]=(Edge){to,len,head[from]};head[from]=tot;
edge[++tot]=(Edge){from,0,head[to]};head[to]=tot;
}
queue<int>q;
bool bfs()
{
while(!q.empty())
q.pop();
m(d,0);
q.push(s);
d[s]=1;
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=head[x];i;i=edge[i].nex)
{
int y=edge[i].to,l=edge[i].len;
if(!d[y]&&l)
{
d[y]=d[x]+1;
q.push(y);
if(y==t)
return 1;
}
}
}
return 0;
}
int dinic(int x,int flow)
{
if(x==t)
return flow;
int res=flow,k;
for(int i=head[x];i&&res;i=edge[i].nex)
{
int y=edge[i].to,l=edge[i].len;
if(l&&d[y]==d[x]+1)
{
k=dinic(y,min(res,l));
if(!k)
{
d[y]=0;
continue;
}
edge[i].len-=k;
edge[i^1].len+=k;
res-=k;
}
}
return flow-res;
}
int main()
{
int n,m,cas=0;
while(~scanf("%d%d",&n,&m))
{
m(head,0);
tot=1;
s=0,t=n*m+1;
int x;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
int x;
scanf("%d",&x);
int k=(i-1)*m+j;
if(i>1)
add(k,k-m,1);
if(i<n)
add(k,k+m,1);
if(j>1)
add(k,k-1,1);
if(j<m)
add(k,k+1,1);
if(x==1)
add(k,t,4);
if(x==2)
add(s,k,4);
}
int maxflow=0;
while(bfs())
maxflow+=dinic(s,INF);
printf("Case %d:\n%d\n",++cas,maxflow);
}
}